0

I had been tasked with writing a script that takes two ini files and merges them, one being the original and the second and more authoritative one being the change file. So basically anything that's new in the change file gets added, and anything that's a duplicate gets changed. And it works.... but not really how I expected.

I basically decided to do a diff on the sections using a list, and then iterate over that list and add in the deltas, but the behavior I'm seeing is hard for me to explain. Currently if there are no section changes nothing gets changed, that makes sense since you can't iterate over a list of nothing. However if even one new section gets added it merges all the option values from all over the other sections, changed or not. Which in a nut shell is what I want but I don't understand why, except for the fact that no new sections are present in the change file you'd have to add just a dummy entry to get it to actually parse.

Here's my code:

#!/usr/bin/env python
#Import Config Parser and modules, sys can be removed
#I'd like to keep it for debugging for future versions

from ConfigParser import SafeConfigParser
import sys, argparse

###############################
# Voyager Parser              #
# Written March 2014          #
# Clifford Trueman            #
###############################

__NAME__   ='voyager_parser'
__VERSION__='0.1'
__USAGE__  ='./voyager_parser -i <inputfile> -c <changefile> -o <outputfile>'
__SUMMARY__='Script to merge changes from PCE and GOI'


parse_cli = argparse.ArgumentParser(description='voyager_parser: To read in and merge GOI and PCE change ini\'s')
parse_cli.add_argument('-i', '--input', help='Input original GOI file name',required=True)
parse_cli.add_argument('-c', '--change', help='Input PCE derived ini file for changes',required=True)
parse_cli.add_argument('-o', '--output', help='Output', required=True)


#Define our global variables
#Define two parsers so we can work with multiple files
args         = parse_cli.parse_args()
parser       = SafeConfigParser()
parser2      = SafeConfigParser()
list1        = []
list2        = []
input_file1  = args.input
input_file2  = args.change
output_file  = args.output


########################
# Define our Functions #
########################

#Figuring out section diffs, Source - change files --input and --change file order matters!
def read_file_sections(input_file, compare_list):
    parser.read(input_file)
    for merge in parser.sections():
        compare_list.append(merge)
    return compare_list

#Take what we found to be different then add it
def add_delta_sections(delta_list, output_file):
    for delta in delta_list:
        parser2.add_section(delta)
        parser.write(sys.stdout)#comment in for debugging
        parser.write(open(output_file, 'w'))
    return 

######################
# Call our functions #
######################

#get a list of the sections in both ini files 
read_file_sections(input_file1, list1)
read_file_sections(input_file2, list2)

#Find out what that difference is
delta_list = list(set(list2)-set(list1))
print delta_list
#Call this to add in the changes we found
add_delta_sections(delta_list, output_file)


__name__ == '__main__'
Valentin Lorentz
  • 9,556
  • 6
  • 47
  • 69
c4ifford
  • 11
  • 2
  • One thing I did note is that setting delta_list variable it seems to produce the same output if the list are subtracted or added which seems odd, both resulting in delta_list = [] if there are no changes to any of the sections. I'm in the process of looking into this. – c4ifford Mar 05 '14 at 17:31

1 Answers1

1

So I realized after breaking down the code into sections, that ConfigParser was doing a lot of the heavy lifting I was trying to do around it, What I found was that loading the files in sequence actually did the diff I wanted internally to the module. So in a nut shell just loading two files and into a parser and then writing the parser buffer back out gives you the diff I wanted.

anyhow here's what I changed it to:

#Define our global variables
 27 args         = parse_cli.parse_args()
 28 parser       = SafeConfigParser()
 29 input_file1  = args.input
 30 input_file2  = args.change
 31 output_file  = args.output
 32 
 33 
 34 ########################
 35 # Define our Functions #
 36 ########################
 37 
 38 def read_file_sections(input_file):
 39     parser.read(input_file)
 40     return
 41 
 42 def merge_sections(output_file):
 43     parser.write(sys.stdout)#comment in for debugging
 44     parser.write(open(output_file, 'w'))
 45     return
 46 
 47 ######################
 48 # Call our functions #
 49 ######################
 50 
 51 read_file_sections(input_file1)
 52 read_file_sections(input_file2)
 53 merge_sections(output_file)
c4ifford
  • 11
  • 2