#!/usr/bin/env python3 import os, sys, json, traceback, subprocess # Definitions def stdout(string, end='\n', flush=False): print(string, end=end, file=sys.stdout, flush=flush) def stderr(string, end='\n', flush=False): print(string, end=end, file=sys.stderr, flush=flush) exit_codes = { "normal exit": 0, "wrong usage": 1, "error while processing": 2 } stderr("\nVariable Grabbler - version 5.0\n--------------------------------------------------------------------------------") ################################################################################ # Chnages in this version: # - complete rewrite in Python 3 # - output to stdout instead of rewriting the file #=============================================================================== # Full documentation: tbd #=============================================================================== # Command line input handling usage = "Usage: python3 "+sys.argv[0]+" " if not len(sys.argv)==3: stderr("E: Wrong amount of arguments.") stderr(usage) sys.exit(exit_codes["wrong usage"]) if sys.argv[1] == sys.argv[2]: stderr("E: Both input files are the same.") stderr(usage) sys.exit(exit_codes["wrong usage"]) # load macros into a dict stderr("I: Reading macro definitions... ") macros = {} try: if os.path.isfile(sys.argv[1]): macro_file = open(sys.argv[1], "r") macros = json.loads(macro_file.read()) macro_file.close() elif sys.argv[1] == '-': macros = json.loads(sys.stdin.read()) else: stderr("E: Not a valid file: "+sys.argv[1]) sys.exit(exit_codes["error while processing"]) except: stderr("E: An exception occurred while trying to read macro definitions:") traceback.print_exc() sys.exit(exit_codes["error while processing"]) # process "file" and "exec" macros stderr("I: Loading templates and processing commands...") for macro in macros: if macros[macro][0] == "file": if os.path.isfile(macros[macro][1]): try: stderr("I: Loading template: " + macro) template = open(macros[macro][1], "r") macros[macro] = template.read() template.close() except: stderr("E: An exception occurred while trying to read the template:") traceback.print_exc() sys.exit(exit_codes["error while processing"]) else: stderr("E: Macro \"" + macro + "\": template \"" + macros[macro][1] + "\" is not a valid file.") sys.exit(exit_codes["error while processing"]) elif macros[macro][0] == "exec": try: stderr("I: Running command: " + macro) process = subprocess.Popen(macros[macro][1], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) process_stdout, process_stderr = process.communicate() macros[macro] = process_stdout.decode("utf-8") if len(process_stderr) > 0: stderr("Output on stderr:\n"+process_stderr) if not process.returncode == 0: stderr("E: Command execution failed with exit code "+str(process.returncode)) sys.exit(exit_codes["error while processing"]) except: stderr("E: An exception occurred while trying to process the command:") traceback.print_exc() sys.exit(exit_codes["error while processing"]) # open file to be processed and iterate over it stderr("I: Preparing to process input file...") try: input_file = sys.stdin if os.path.isfile(sys.argv[2]): input_file = open(sys.argv[2], "r") elif sys.argv[2] == '-': # nothing to do here bc input_file is already set to sys.stdin pass else: stderr("E: Not a valid file: "+sys.argv[2]) sys.exit(exit_codes["error while processing"]) # make the magic happen stderr("I: Processing input file...") for line in input_file: for macro in macros: line = line.replace("%" + macro + "%", str(macros[macro])) stdout(line, end="") # close input file if it's not sys.stdin, assume sys.stdin is being handled for us if not input_file==sys.stdin: input_file.close() except: stderr("E: An exception occured while processing " + input_file.name + ":") traceback.print_exc() sys.exit(exit_codes["error while processing"])