1*f4a2713aSLionel Sambuc""" 2*f4a2713aSLionel SambucDefines utilities useful for performing standard "configuration" style tasks. 3*f4a2713aSLionel Sambuc""" 4*f4a2713aSLionel Sambuc 5*f4a2713aSLionel Sambucimport re 6*f4a2713aSLionel Sambucimport os 7*f4a2713aSLionel Sambuc 8*f4a2713aSLionel Sambucdef configure_file(input_path, output_path, substitutions): 9*f4a2713aSLionel Sambuc """configure_file(input_path, output_path, substitutions) -> bool 10*f4a2713aSLionel Sambuc 11*f4a2713aSLionel Sambuc Given an input and output path, "configure" the file at the given input path 12*f4a2713aSLionel Sambuc by replacing variables in the file with those given in the substitutions 13*f4a2713aSLionel Sambuc list. Returns true if the output file was written. 14*f4a2713aSLionel Sambuc 15*f4a2713aSLionel Sambuc The substitutions list should be given as a list of tuples (regex string, 16*f4a2713aSLionel Sambuc replacement), where the regex and replacement will be used as in 're.sub' to 17*f4a2713aSLionel Sambuc execute the variable replacement. 18*f4a2713aSLionel Sambuc 19*f4a2713aSLionel Sambuc The output path's parent directory need not exist (it will be created). 20*f4a2713aSLionel Sambuc 21*f4a2713aSLionel Sambuc If the output path does exist and the configured data is not different than 22*f4a2713aSLionel Sambuc it's current contents, the output file will not be modified. This is 23*f4a2713aSLionel Sambuc designed to limit the impact of configured files on build dependencies. 24*f4a2713aSLionel Sambuc """ 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc # Read in the input data. 27*f4a2713aSLionel Sambuc f = open(input_path, "rb") 28*f4a2713aSLionel Sambuc try: 29*f4a2713aSLionel Sambuc data = f.read() 30*f4a2713aSLionel Sambuc finally: 31*f4a2713aSLionel Sambuc f.close() 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc # Perform the substitutions. 34*f4a2713aSLionel Sambuc for regex_string,replacement in substitutions: 35*f4a2713aSLionel Sambuc regex = re.compile(regex_string) 36*f4a2713aSLionel Sambuc data = regex.sub(replacement, data) 37*f4a2713aSLionel Sambuc 38*f4a2713aSLionel Sambuc # Ensure the output parent directory exists. 39*f4a2713aSLionel Sambuc output_parent_path = os.path.dirname(os.path.abspath(output_path)) 40*f4a2713aSLionel Sambuc if not os.path.exists(output_parent_path): 41*f4a2713aSLionel Sambuc os.makedirs(output_parent_path) 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc # If the output path exists, load it and compare to the configured contents. 44*f4a2713aSLionel Sambuc if os.path.exists(output_path): 45*f4a2713aSLionel Sambuc current_data = None 46*f4a2713aSLionel Sambuc try: 47*f4a2713aSLionel Sambuc f = open(output_path, "rb") 48*f4a2713aSLionel Sambuc try: 49*f4a2713aSLionel Sambuc current_data = f.read() 50*f4a2713aSLionel Sambuc except: 51*f4a2713aSLionel Sambuc current_data = None 52*f4a2713aSLionel Sambuc f.close() 53*f4a2713aSLionel Sambuc except: 54*f4a2713aSLionel Sambuc current_data = None 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc if current_data is not None and current_data == data: 57*f4a2713aSLionel Sambuc return False 58*f4a2713aSLionel Sambuc 59*f4a2713aSLionel Sambuc # Write the output contents. 60*f4a2713aSLionel Sambuc f = open(output_path, "wb") 61*f4a2713aSLionel Sambuc try: 62*f4a2713aSLionel Sambuc f.write(data) 63*f4a2713aSLionel Sambuc finally: 64*f4a2713aSLionel Sambuc f.close() 65*f4a2713aSLionel Sambuc 66*f4a2713aSLionel Sambuc return True 67