#!/usr/bin/env python3 """ This utility script helps in the creation of experiment setups. It therefore reads experiment descriptions from json files and creates everything necessary as a result. It therefore performs the following actions: * [x] Read the json file of every experiment * [x] Create folders for every experiment * [ ] Create the header file for every experiment * [x] Add the make file for every experiment * [x] Add c++ file for every experiment """ import sys import os import argparse import shutil import json import pystache class UtilityFunctions(pystache.TemplateSpec): def Upper(self, text=None): """ Capitalize a given token """ return lambda txt: txt.upper() def Lower(self, text=None): """ Return the given text in lowercase. """ return lambda txt: txt.lower() def CamelCase(self, text=None): """ Capitalize the first letter of the given text. """ def _camel(text): text[0].upper() return text return _camel def query_yes_no(question, default=None): """ Queries the user for a decision. """ if default is None: prompt = ' [y/n]' elif default.lower() == 'yes': prompt = ' [Y/n]' elif default.lower() == 'no': prompt = ' [y/N]' else: raise ValueError('Invalid default answer {}'.format(default)) while True: print(question, prompt, end='') choice = input().lower() if 'yes'.find(choice) == 0: return True elif 'no'.find(choice) == 0: return False def create_dir(filename): """ Create the directory denoted by filename, if it doesn't exists. Ask for its removal if it exists. """ try: os.makedirs(filename) except FileExistsError: if not query_yes_no('Folder exists, remove?', default='yes'): return False shutil.rmtree(filename) os.makedirs(filename) return True def create_header(headerfile, experiment, destination): """ Create a header file for the experiment. """ with open(headerfile, 'r') as header_template: template = header_template.read() header_txt = pystache.render(template, experiment, UtilityFunctions()) with open(destination, 'w') as header: print(header_txt, file=header) def main(): """ Starting point of the script, parses arguments and creates the experiments. """ parser = argparse.ArgumentParser(description='Generate experiment data.') parser.add_argument('description', type=str, nargs='+', help='file containing the taskset description.') parser.add_argument('--header', dest='header', type=str, nargs='?', default='./templates/normal/defines.h', help='path to optional custom header file.') parser.add_argument('--makefile', dest='makefile', type=str, nargs='?', default='./templates/normal/Makefile', help='path to optional custom makefile.') parser.add_argument('--cpp', dest='cpp', type=str, nargs='*', default='./templates/normal/experiment.cpp', help='path to optional custom c++ implementation.') args = parser.parse_args() cwd = os.getcwd() for num, experiment_file in enumerate(args.description): with open(experiment_file, 'r') as experiment_description: descr_json = experiment_description.read() experiment = json.loads(descr_json) print('[{}/{}] Creating experiment {}:'.format(num + 1, len(args.description), experiment['name']), file=sys.stderr) experiment_dir = os.path.join(cwd, experiment['name']) # Create folder print('Create folder…', experiment_dir, file=sys.stderr) if not create_dir(experiment_dir): print('Skipping experiment ', experiment['name'], file=sys.stderr) continue # Add header print('Create header file…', file=sys.stderr) header_path = os.path.join(experiment_dir, 'defines.h') create_header(args.header, experiment, header_path) # Add makefile & c++ file print('Adding Makefile…', file=sys.stderr) makefile_path = os.path.join(experiment_dir, 'Makefile') shutil.copyfile(args.makefile, makefile_path) print('Add C++ file(s)…', file=sys.stderr) cpp_file_path = os.path.join(experiment_dir, 'experiment.cpp') shutil.copyfile(args.cpp, cpp_file_path) if __name__ == '__main__': main()