labpack/compilers/yaml.py
def merge_yaml_strings(*sources, output=''):

    '''
        method for merging two or more yaml strings

    this method walks the parse tree of yaml data to merge the fields
    (and comments) found in subsequent sources into the data structure of the
    initial sources. any number of sources can be added to the source args, but
    only new fields and new comments from subsequent sources will be added. to
    overwrite the values in the initial source, it suffices to simply reverse 
    the order of the sources

    PLEASE NOTE:    since there is no way to uniquely identify list items between
                    two yaml documents, items are not added to existing lists.

    PLEASE NOTE:    however, lists are transversed in order to evaluate comments
                    and keys of nested dictionaries using the first item of any
                    subsequent list as a model for the scope

    PLEASE NOTE:    the way that ruamel.yaml keeps track of multi-line comments
                    can create odd results for comments which appear at the start
                    or the end of lists and dictionaries when new fields and comments 
                    are added. it is best to restrict comments to the start of lists
                    and dictionaries.

    :param sources: variable-length argument list of strings with yaml text
    :param output: [optional] string with type of output: '' [default], io
    :return: string with merged data [or StringIO object]
    '''

    # import libraries
    import re
    from copy import deepcopy
    from ruamel.yaml.compat import StringIO
    from ruamel.yaml.util import load_yaml_guess_indent
    yml = YAML(typ='rt')
    yml.default_flow_style = False

    # define variables
    combined = None
    indent = 2
    seq_indent = 0
    combined_head = None

    # open and combine sources
    for text in sources:
        result, indent, seq_indent = load_yaml_guess_indent(text)
        data = yml.load(text)
        try:
            head = [comment.value for comment in data.ca.comment[1]]
        except:
            if ruamel_yaml_version <= (0, 17, 0):
                raise
            else:
                raise NotImplementedError
        if not isinstance(data, CommentedMap) and not isinstance(data, CommentedSeq):
            raise ValueError('Source documents must be either lists or dictionaries.')
        if not combined:
            combined = deepcopy(data)
            combined_head = head
        elif combined.__class__.__name__ != data.__class__.__name__:
            pass
            # raise ValueError('Source documents must be the same top-level datatype or use rule="overwrite"')
        else:
            walk_data(combined, data)

        # add comments to head of document
        if head:
            for comment in head:
                if comment not in combined_head:
                    combined_head.append(comment)
            head_comments = []
            for comment in combined_head:
                comment = re.sub('^# ?','',comment)
                comment = re.sub('\n$','',comment)
                head_comments.append(comment)
            lines = '\n'.join(head_comments)
            combined.yaml_set_start_comment(lines, indent=0)

    # apply indentation and return string
    stream = StringIO()
    yml.indent(sequence=indent, offset=seq_indent)
    yml.dump(combined, stream)
    if output == 'io':
        return stream
    return stream.getvalue()

        method for merging two or more yaml strings

    this method walks the parse tree of yaml data to merge the fields
    (and comments) found in subsequent sources into the data structure of the
    initial sources. any number of sources can be added to the source args, but
    only new fields and new comments from subsequent sources will be added. to
    overwrite the values in the initial source, it suffices to simply reverse 
    the order of the sources

    PLEASE NOTE:    since there is no way to uniquely identify list items between
                    two yaml documents, items are not added to existing lists.

    PLEASE NOTE:    however, lists are transversed in order to evaluate comments
                    and keys of nested dictionaries using the first item of any
                    subsequent list as a model for the scope

    PLEASE NOTE:    the way that ruamel.yaml keeps track of multi-line comments
                    can create odd results for comments which appear at the start
                    or the end of lists and dictionaries when new fields and comments 
                    are added. it is best to restrict comments to the start of lists
                    and dictionaries.

    :param sources: variable-length argument list of strings with yaml text
    :param output: [optional] string with type of output: '' [default], io
    :return: string with merged data [or StringIO object]
    
method for merging two or more yaml strings
this method walks the parse tree of yaml data to merge the fields
(and comments) found in subsequent sources into the data structure of the
initial sources. any number of sources can be added to the source args, but
only new fields and new comments from subsequent sources will be added. to
overwrite the values in the initial source, it suffices to simply reverse
the order of the sources

PLEASE NOTE:    since there is no way to uniquely identify list items between
two yaml documents, items are not added to existing lists.

PLEASE NOTE:    however, lists are transversed in order to evaluate comments
and keys of nested dictionaries using the first item of any
subsequent list as a model for the scope

PLEASE NOTE:    the way that ruamel.yaml keeps track of multi-line comments
can create odd results for comments which appear at the start
or the end of lists and dictionaries when new fields and comments
are added. it is best to restrict comments to the start of lists
and dictionaries.
method for merging two or more yaml strings this method walks the parse tree of yaml data to merge the fields ( and comments ) found in subsequent sources into the data structure of the initial sources . any number of sources can be added to the source args but only new fields and new comments from subsequent sources will be added . to overwrite the values in the initial source it suffices to simply reverse the order of the sources PLEASE NOTE : since there is no way to uniquely identify list items between two yaml documents items are not added to existing lists . PLEASE NOTE : however lists are transversed in order to evaluate comments and keys of nested dictionaries using the first item of any subsequent list as a model for the scope PLEASE NOTE : the way that ruamel . yaml keeps track of multi - line comments can create odd results for comments which appear at the start or the end of lists and dictionaries when new fields and comments are added . it is best to restrict comments to the start of lists and dictionaries .
def merge_yaml_strings(*sources, output=''):
    import re
    from copy import deepcopy
    from ruamel.yaml.compat import StringIO
    from ruamel.yaml.util import load_yaml_guess_indent
    yml = YAML(typ='rt')
    yml.default_flow_style = False
    combined = None
    indent = 2
    seq_indent = 0
    combined_head = None
    for text in sources:
        result, indent, seq_indent = load_yaml_guess_indent(text)
        data = yml.load(text)
        try:
            head = [comment.value for comment in data.ca.comment[1]]
        except:
            if ruamel_yaml_version <= (0, 17, 0):
                raise
            else:
                raise NotImplementedError
        if not isinstance(data, CommentedMap) and not isinstance(data, CommentedSeq):
            raise ValueError('Source documents must be either lists or dictionaries.')
        if not combined:
            combined = deepcopy(data)
            combined_head = head
        elif combined.__class__.__name__ != data.__class__.__name__:
            pass
        else:
            walk_data(combined, data)
        if head:
            for comment in head:
                if comment not in combined_head:
                    combined_head.append(comment)
            head_comments = []
            for comment in combined_head:
                comment = re.sub('^# ?','',comment)
                comment = re.sub('\n$','',comment)
                head_comments.append(comment)
            lines = '\n'.join(head_comments)
            combined.yaml_set_start_comment(lines, indent=0)
    stream = StringIO()
    yml.indent(sequence=indent, offset=seq_indent)
    yml.dump(combined, stream)
    if output == 'io':
        return stream
    return stream.getvalue()
def merge_yaml_strings ( * sources , output = '' ) : import re from copy import deepcopy from ruamel . yaml . compat import StringIO from ruamel . yaml . util import load_yaml_guess_indent yml = YAML ( typ = 'rt' ) yml . default_flow_style = False combined = None indent = 2 seq_indent = 0 combined_head = None for text in sources : result , indent , seq_indent = load_yaml_guess_indent ( text ) data = yml . load ( text ) try : head = [ comment . value for comment in data . ca . comment [ 1 ] ] except : if ruamel_yaml_version <= ( 0 , 17 , 0 ) : raise else : raise NotImplementedError if not isinstance ( data , CommentedMap ) and not isinstance ( data , CommentedSeq ) : raise ValueError ( 'Source documents must be either lists or dictionaries.' ) if not combined : combined = deepcopy ( data ) combined_head = head elif combined . __class__ . __name__ != data . __class__ . __name__ : pass else : walk_data ( combined , data ) if head : for comment in head : if comment not in combined_head : combined_head . append ( comment ) head_comments = [ ] for comment in combined_head : comment = re . sub ( '^# ?' , '' , comment ) comment = re . sub ( '\n$' , '' , comment ) head_comments . append ( comment ) lines = '\n' . join ( head_comments ) combined . yaml_set_start_comment ( lines , indent = 0 ) stream = StringIO ( ) yml . indent ( sequence = indent , offset = seq_indent ) yml . dump ( combined , stream ) if output == 'io' : return stream return stream . getvalue ( )
method for merging two or more yaml strings
this method walks the parse tree of yaml data to merge the fields
(and comments) found in subsequent sources into the data structure of the
initial sources.
method for merging two or more yaml strings this method walks the parse tree of yaml data to merge the fields ( and comments ) found in subsequent sources into the data structure of the initial sources .
'''
        method for merging two or more yaml strings

    this method walks the parse tree of yaml data to merge the fields
    (and comments) found in subsequent sources into the data structure of the
    initial sources. any number of sources can be added to the source args, but
    only new fields and new comments from subsequent sources will be added. to
    overwrite the values in the initial source, it suffices to simply reverse 
    the order of the sources

    PLEASE NOTE:    since there is no way to uniquely identify list items between
                    two yaml documents, items are not added to existing lists.

    PLEASE NOTE:    however, lists are transversed in order to evaluate comments
                    and keys of nested dictionaries using the first item of any
                    subsequent list as a model for the scope

    PLEASE NOTE:    the way that ruamel.yaml keeps track of multi-line comments
                    can create odd results for comments which appear at the start
                    or the end of lists and dictionaries when new fields and comments 
                    are added. it is best to restrict comments to the start of lists
                    and dictionaries.

    :param sources: variable-length argument list of strings with yaml text
    :param output: [optional] string with type of output: '' [default], io
    :return: string with merged data [or StringIO object]
    ''' # import libraries # define variables # open and combine sources # raise ValueError('Source documents must be the same top-level datatype or use rule="overwrite"') # add comments to head of document # apply indentation and return string
string with merged data [or StringIO object]
string with merged data [ or StringIO object ]
output
[optional] string with type of output: '' [default], io
[ optional ] string with type of output : ' ' [ default ] io
sources
variable-length argument list of strings with yaml text
variable - length argument list of strings with yaml text