'This parses the lines of a batchfile according to the following
rules:
Args:
pythonpath (str): The dot-python path to the file.
Returns:
codeblocks (list): A list of all #CODE blocks, each with
prepended #HEADER data. If no #CODE blocks were found,
this will be a list of one element.
Notes:
1. Code before a #CODE/HEADER block are considered part of
the first code/header block or is the ONLY block if no
#CODE/HEADER blocks are defined.
2. Lines starting with #HEADER starts a header block (ends other blocks)
3. Lines starting with #CODE begins a code block (ends other blocks)
4. Lines starting with #INSERT are on form #INSERT filename. Code from
this file are processed with their headers *separately* before
being inserted at the point of the #INSERT.
5. Code after the last block is considered part of the last header/code
block'

def parse_file(self, pythonpath):

    text = ''.join(read_batchfile(pythonpath, file_ending='.py'))
    def replace_insert(match):
        'Run    parse_file    on    the    import    before    sub:ing    it    into    this    file'
        path = match.group(1)
        return (('#    batchcode    insert    (%s):' % path) + '\n'.join(self.parse_file(path)))
    text = _RE_INSERT.sub(replace_insert, text)
    headers = []
    codes = []
    for (imatch, match) in enumerate(list(_RE_CODE_OR_HEADER.finditer(text))):
        mtype = match.group(1)
        (istart, iend) = match.span(2)
        code = text[istart:iend]
        if (mtype == '#HEADER'):
            headers.append(code)
        else:
            codes.append(code)
    header = (('#    batchcode    header:\n%s\n\n' % '\n\n'.join(headers)) if headers else '')
    codes = [('%s#    batchcode    code:\n%s' % (header, code)) for code in codes]
    return codes
