Python insert line in the middle of the file I will be inserting a new text line in a setup.py file, this new line will contain text, and is part of the REQUIRED_PACKAGES. I parsed the 
file and look for REQUIRED_PACKAGES pattern (REQUIRED_PACKAGES = [ ... ]). Looking for alternatives during file insertion.

A sample setup.py file looks like this:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import fnmatch
import os
import re
import sys

from setuptools import Command
from setuptools import find_packages
from setuptools import setup
from setuptools.command.install import install as InstallCommandBase
from setuptools.dist import Distribution

DOCLINES = __doc__.split('\n')

_VERSION = '1.0.0'

REQUIRED_PACKAGES = [
    'absl-py &gt;= 0.7.0',
    'astunparse == 1.6.3',
    'backports.weakref &gt;= 1.0rc1;python_version&lt;"3.4"',
    'enum34 &gt;= 1.1.6;python_version&lt;"3.4"',
    'gast == 0.3.3',
    'scipy == 1.2.2;python_version&lt;"3"',
]

if sys.byteorder == 'little':
  # grpcio does not build correctly on big-endian machines due to lack of
  # BoringSSL support.  
  REQUIRED_PACKAGES.append('io &gt;= 1.0.0')

...


After conversion it will look like this (adding a new line):

...
REQUIRED_PACKAGES = [
    'absl-py &gt;= 0.7.0',
    'astunparse == 1.6.3',
    'backports.weakref &gt;= 1.0rc1;python_version&lt;"3.4"',
    'enum34 &gt;= 1.1.6;python_version&lt;"3.4"',
    'gast == 0.3.3',
    'scipy == 1.2.2;python_version&lt;"3"',
    'test==1.0.0',
]
...


Python code

import re


SEARCH_DICT = {
    'required_packages': re.compile(
        r'REQUIRED_PACKAGES = (?P&lt;required_packages&gt;.*)\n')
}

TEST_LIBRARY = '\t\t\'test==1.0.0\'\n'


def _parse_line(line):
    """
    Do a regex search against all defined regexes and
    return the key and match result of the first matching regex

    """

    for key, rx in SEARCH_DICT.items():
        match = rx.search(line)
        if match:
            return key, match
    # if there are no matches
    return None, None


def parse_file(filepath):
    """
    Parse text at given filepath

    Parameters
    ----------
    filepath : str
        Filepath for file_object to be parsed

    Returns
    -------
    data : file contents

    while True:
        last_pos = fp.tell()
        line = fp.readline()
        new_line = line.upper()
        fp.seek(last_pos)
        fp.write(new_line)
        print "Read %s, Wrote %s" % (line, new_line)


    """

    data = []  # create an empty list to collect the data
    line_index = -1 
    # open the file and read through it line by line

    with open(filepath, 'r+') as file_object:
        line = file_object.readline()
        line_index+=1
        while line:
            # at each line check for a match with a regex
            key, match = _parse_line(line)
            if key == 'required_packages':
                required_packages_start = match.group('required_packages')
                if required_packages_start == '[':                    
                    print('Found REQUIRED_PACKAGES')
                    while line.strip():                        
                        library = line.rstrip()
                        if library == ']': # End of required packages
                            return line_index
                        line = file_object.readline()
                        line_index+=1                     

            line = file_object.readline()  
            line_index+=1          
        file_object.readline()
        line_index+=1

    return line_index


line_index = parse_file('setup.py')
lines = None
if line_index != -1:
    with open('setup.py', 'r+') as fd:
        contents = fd.readlines()
        contents.insert(line_index, TEST_LIBRARY)  # new_string should end in a newline
        fd.seek(0)  # readlines consumes the iterator, so we need to start over
        fd.writelines(contents)  # No need to truncate as we are increasing filesize
Your code goes through the file twice - once to find the index where your new line is to be inserted, and again to actually perform the change.

My approach to this problem would be to create a class that contains three variables:


The lines in setup.py before "REQUIRED_PACKAGES = ["
The contents of the REQUIRED_PACKAGES list
The lines in setup.py after the REQUIRED_PACKAGES list


Your problem then splits nicely into three distinct sub-problems:


Parsing setup.py and returning an instance of the class above
Adding an element to the required packages list in your custom class (trivial)
Writing a new setup.py file


Looking at your code specifically, your docstring for parse_file does not match what the code is doing. It says that data is returned, but the code actually returns line_index, and the data member you initialise is unused.

Your code comments in general could be improved. You comment some obvious things such as"open the file and read through it line by line" and "if there are no matches". These operations are immediately apparent from looking at the code, and do not require comments.