#! /usr/bin/env python # ========================================================================== # ctools code generator # # Copyright (C) 2018 Juergen Knoedlseder # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # ========================================================================== import os import sys import glob import commands import fileinput from datetime import date import gammalib # ================= # # Confirm something # # ================= # def confirm(text): """ Confirm something Parameters ---------- text : str Thing to confirm Returns ------- flag : bool True if something is confirmed """ # Confirmation loop waiting = True while waiting: confirmation = str(raw_input(text+' (y/n): ')) if confirmation == 'q': sys.exit() elif confirmation == 'y': flag = True waiting = False elif confirmation == 'n': flag = False waiting = False # Return confirmation flag return flag # ============ # # Get response # # ============ # def response(text, confirm_response=False): """ Get response Parameters ---------- text : str Thing we want to get a response to confirm_response : bool True if response should be confirmed Returns ------- response : str Reponse """ # Looping until response is accepted looping = True while looping: # Get response from input waiting = True while waiting: response = str(raw_input('%s: ' % text)) if response == 'q': sys.exit() else: waiting = False # If the version number change is confirmed then do the change if confirm_response: if confirm('Is "%s" ok?' % response): looping = False else: looping = False # Return response return response # ======== # # Add file # # ======== # def add_file(infile, outfile, tokens): """ Add a file, replacing all tokens Parameters ---------- infile : str Input filename outfile : str Output filename tokens : list of dict Token list """ # Create output file file = open(outfile, "w") # Initialise number of header lines n_header = 0 # Loop over input file for line in open(infile, 'r'): # Signal if this is a header line is_header_ast = False is_header_hash = False if len(line) > 75: is_header_ast = line[1] == '*' and line[75] == '*' is_header_hash = line[0] == '#' and line[1] == ' ' and line[76] == '#' n_header += 1 # Replace tokens in line for token in tokens: line = line.replace(token['pattern'], token['string']) # If we have a header line than format the line if is_header_ast: text = line.strip(' *\n') if n_header == 2: line = ' *'+gammalib.centre(text,73)+'*\n' elif n_header == 4: line = ' *'+gammalib.left(' '+text,73)+'*\n' if is_header_hash: text = line.strip(' #\n') line = '# '+gammalib.left(text,74)+'#\n' # Write out line file.write(line) # Close file file.close() # Return return # ========== # # Set tokens # # ========== # def set_tokens(classname, author, what): """ Set replacement tokens for a ctool or cscript """ # Get current year year = str(date.today().year) # Set tokens tokens = [{'pattern': 'xxx', 'string': classname}, {'pattern': 'XXX', 'string': classname.upper()}, {'pattern': '[WHAT]', 'string': what}, {'pattern': '[what]', 'string': what.lower()}, {'pattern': '[AUTHOR]', 'string': author}, {'pattern': '[YEAR]', 'string': year}] # Return tokens return tokens # ========= # # Add ctool # # ========= # def add_ctool(name, tokens, baseclass): """ Add an instrument class Parameters ---------- name : str ctool or script name tokens : str Tokens for replacement baseclass : str Baseclass """ # Create directory structure if not os.path.isdir('src/%s' % name): os.mkdir('src/%s' % name) # Set template file names inctemp = 'src/template/ctool_%s.hpp' % (baseclass) srctemp = 'src/template/ctool_%s.cpp' % (baseclass) pytemp = 'src/template/ctool_%s.i' % (baseclass) partemp = 'src/template/ctool.par' maintemp = 'src/template/main.cpp' maketemp = 'src/template/ctool_Makefile.am' testtemp = 'src/template/ctool_test.py' # Set destination file names incfile = 'src/%s/%s.hpp' % (name, name) srcfile = 'src/%s/%s.cpp' % (name, name) parfile = 'src/%s/%s.par' % (name, name) mainfile = 'src/%s/main.cpp' % (name) makefile = 'src/%s/Makefile.am' % (name) pyfile = 'pyext/%s.i' % (name) testfile = 'test/test_%s.py' % (name) # Add files add_file(inctemp, incfile, tokens) add_file(srctemp, srcfile, tokens) add_file(partemp, parfile, tokens) add_file(maintemp, mainfile, tokens) add_file(maketemp, makefile, tokens) add_file(pytemp, pyfile, tokens) add_file(testtemp, testfile, tokens) # Update src/Makefile.am filename = 'src/Makefile.am' insertline1 = ' %s ' % (name) insertline2 = ' %s/lib%s.la ' % (name, name) for line in fileinput.FileInput(filename,inplace=1): if 'SUBDIRS' in line.replace(' ', ''): last = line[-2] line = line.replace(line, line+insertline1+last+'\n') if 'libctools_la_LIBADD' in line.replace(' ', ''): last = line[-2] line = line.replace(line, line+insertline2+last+'\n') print line, # Update Python module for line in fileinput.FileInput('pyext/ctools/tools.i',inplace=1): if '%include "ctbin.i"' in line: print('%%include "%s.i"' % (name)) print line, # Update unit test for line in fileinput.FileInput('test/test_python_ctools.py',inplace=1): if 'import test_ctbin' in line: print('import test_%s' % (name)) elif 'test_ctbin.Test()' in line: print(' test_%s.Test(),' % (name)) print line, # Update export of unit test for line in fileinput.FileInput('pyext/Makefile.am',inplace=1): if '$(top_srcdir)/test/test_ctbin.py' in line: print(' $(top_srcdir)/test/test_%s.py \\' % (name)) print line, # Update configure.ac for line in fileinput.FileInput('configure.ac',inplace=1): if 'src/ctbin/Makefile' in line: print(' src/%s/Makefile' % (name)) print line, # Return return # ============ # # Manage ctool # # ============ # def ctool_menu(): """ Manage ctool """ # Annonce actions print("") print("Add ctool") print("---------") # Stay in loop until there is a final confirmation while True: # Enter information ctoolname = response('Please enter a ctool name (e.g. "ctpntsim")') what = response('Please say what the tool is for (e.g. "Pointing simulation")') author = response('Please enter your name (e.g. "Joe Public")') # Enter baseclass print('From which baseclass should the ctool derive?') print('[1] ctool') print('[2] ctobservation') print('[3] ctlikelihood') waiting = True choice = 1 while waiting: choice = str(raw_input('Enter your choice: ')) if choice == '1' or choice == '2' or choice == '3': waiting = False if choice == '1': basename = 'base' baseclass = 'ctool' elif choice == '2': basename = 'obs' baseclass = 'ctobservation' elif choice == '3': basename = 'like' baseclass = 'ctlikelihood' # Ask to confirm module summary print('\nAll right. Have now:') print('ctool name ......: "%s"' % ctoolname) print('Tools descriptor : "%s"' % what) print('Your name .......: "%s"' % author) print('Base class ......: "%s"' % baseclass) if confirm('Is this correct?'): break # Set tokens tokens = set_tokens(ctoolname, author, what) # Add ctool add_ctool(ctoolname, tokens, basename) # Return return # ================ # # Manage main menu # # ================ # def main_menu(): """ Manage main menu """ # Print main menu print('[1] Add ctool') print('[2] Add cscript') print('[q] Quit') # Wait for the input waiting = True while waiting: choice = str(raw_input('Enter your choice: ')) if choice == '1' or choice == '2' or choice == 'q': waiting = False # Return choice return choice # ======================== # # Main routine entry point # # ======================== # if __name__ == '__main__': # Check if script has been started from ctools root directory if not os.path.isfile('ctools.pc.in'): print('"codgen.py" script needs to be started from ctools source code ' 'root directory, you are somewhere else. Quit now.') sys.exit() # Clear console os.system('clear') # Print header print('ctools code generator') print('=====================') print('') # Enter endless loop while True: # Show main menu choice = main_menu() # Dispatch according to choice if choice == '1': ctool_menu() print('') elif choice == '2': cscript_menu() print('') elif choice == 'q': break