12f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar""" 22f4415e256274e00b3fd359f2ba395d401079122Daniel DunbarDefines utilities useful for performing standard "configuration" style tasks. 32f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar""" 42f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 52f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbarimport re 62f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbarimport os 72f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 82f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbardef configure_file(input_path, output_path, substitutions): 92f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar """configure_file(input_path, output_path, substitutions) -> bool 102f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 112f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar Given an input and output path, "configure" the file at the given input path 122f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar by replacing variables in the file with those given in the substitutions 132f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar list. Returns true if the output file was written. 142f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 152f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar The substitutions list should be given as a list of tuples (regex string, 162f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar replacement), where the regex and replacement will be used as in 're.sub' to 172f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar execute the variable replacement. 182f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 192f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar The output path's parent directory need not exist (it will be created). 202f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 212f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar If the output path does exist and the configured data is not different than 222f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar it's current contents, the output file will not be modified. This is 232f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar designed to limit the impact of configured files on build dependencies. 242f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar """ 252f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 262f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar # Read in the input data. 272f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f = open(input_path, "rb") 282f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar try: 292f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar data = f.read() 302f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar finally: 312f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f.close() 322f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 332f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar # Perform the substitutions. 342f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar for regex_string,replacement in substitutions: 352f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar regex = re.compile(regex_string) 362f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar data = regex.sub(replacement, data) 372f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 382f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar # Ensure the output parent directory exists. 392f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar output_parent_path = os.path.dirname(os.path.abspath(output_path)) 402f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar if not os.path.exists(output_parent_path): 412f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar os.makedirs(output_parent_path) 422f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 432f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar # If the output path exists, load it and compare to the configured contents. 442f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar if os.path.exists(output_path): 452f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar current_data = None 462f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar try: 472f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f = open(output_path, "rb") 482f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar try: 492f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar current_data = f.read() 502f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar except: 512f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar current_data = None 522f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f.close() 532f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar except: 542f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar current_data = None 552f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 562f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar if current_data is not None and current_data == data: 572f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar return False 582f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 592f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar # Write the output contents. 602f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f = open(output_path, "wb") 612f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar try: 622f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f.write(data) 632f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar finally: 642f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar f.close() 652f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar 662f4415e256274e00b3fd359f2ba395d401079122Daniel Dunbar return True 67