Source code for flash.flmake.setup_parse

"""Code which parses the command line arguments for the setup command."""

import string
import re
import getopt
import sys
import os

# Local imports
# Relative imports needed
from .. import FLASH_SRC_DIR
from . import setup_globals
from .lazy_file import LazyFile
from .setup_globals import gvars, SetupError
from .utils import dir_glob, search_paths


########################## Internal implementation ##########################

# default arguments
ADDL_DEF_ARGS = ["+default"]

# options without arguments
WITHOUT_ARGS = ["auto","1d","2d","3d","portable",
                "makehide", "curvilinear",
                "opt","debug","test", "index-reorder", "strictparams",
                "fbs","help", "noclobber", "nofbs"] # nofbs disables fixedBlockSize
# options with arguments
WITH_ARGS = ["maxblocks","nxb","nyb","nzb","verbose","site","ostype",
             "defines", "objdir", "locsrcdir", "rundir", "with-unit", "unit", "with-library",
             "without-unit","without-library","kill-unit","unitsfile",
             "makefile", "library", "datafiles", "parfile", "tau",
             "gridinterpolation", "geometry", "particlemethods"]


USAGE="""usage:  setup <problem-name> [options] [VAR=VALUE]...

   problem-name: see source/Simulation/SimulationMain directory
   options: 

   (Science Options)
            -auto -[123]d 
            -maxblocks=<#> -nxb=<#> -nyb=<#> -nzb=<#>
            -with-unit=<unit> -with-library=<libname>[,args]
            -without-unit=<unit> -without-library=<libname>

   (Setup and Make Options)
            -verbose=[DEBUG|INFO|WARN|IMPINFO|ERROR] 
            [-site=<site> | -ostype=<ostype>] 
            -makefile=<extension>
            [-opt| -debug | -test ] 
            -objdir=<relative obj directory> 
            -defines=<defines> -unitsfile=<filename>
            -datafiles=<wildcard> -parfile=<filename>
            -fbs -nofbs -tau=<makefile>

   (Misc Options)
            -makehide -noclobber -portable -help

   * For GNU compatibility, options may be prefixed by -- instead of - as well
   * -unit and -library are considered equivalent to 
     -with-unit and -with-library respectively.
   * For information regarding the [VAR=VALUE] options and using 'setup variables' 
     refer to User's Guide.  
   * To read how shortcuts work see README.shortcuts in your bin directory
"""

[docs]def usage(): """Print usage info and exit""" print USAGE ans = raw_input("\nDo you want to see a list of shortcuts I know about [Y/n]?") ans = ans.replace("\n","") if ans.lower() in ["y","yes",""]: if not hasattr(gvars, 'shortcuts'): gvars.init(FLASH_SRC_DIR) gvars.shortcuts = getShortcuts() sitems = gvars.shortcuts.items() sitems.sort() c = 0 for (k,v) in sitems: c = max(c,len(k)) tpl = " %%-%ds %%s" % (c+2) # template for printing the dictionary print "\nTo use a shortcut add '+shortcut' to your setup line." print "For example ./setup Sod -auto +ug\n" for k,v in sitems: print tpl % (k," ".join(v)) raise SetupError("")
[docs]def cleanupCommandLine(args): """Return a lists where all single - options are converted to --""" ans = [] for m in args: if len(m) > 1 and m[0] == "-" and m[1] != "-": ans.append("-"+m) else: ans.append(m) return ans # processes an existing file and returns a dictionary of shortcuts
def getShortcutDict(filename): sfd = file(filename) shortcuts = {} if hasattr(gvars, 'out'): gvars.out.put("Processing Shortcut file: %s" % filename,setup_globals.IMPINFO) for line in sfd: if not line: continue if line[0] == "#": continue line = line.strip() if line and line[-1] in ["\r","\n"]: line = line[:-1] if line and line[-1] in ["\r","\n"]: line = line[:-1] if not line: continue # now we have a valid line parts = line.split(":") value = cleanupCommandLine([x.strip() for x in parts[1:] if x]) shortcuts[parts[0].lower()] = value return shortcuts # shortcuts is a dictionary mapping shortcut to list of arguments # shortcut X is invoked as "+x" option to setup def getShortcuts(): if not os.environ.has_key("SETUP_SHORTCUTS"): if hasattr(gvars, 'out'): gvars.out.put("No Shortcut file specified using default",setup_globals.DEBUG) sfiles = [FLASH_SRC_DIR + "/bin/setup_shortcuts.txt"] else: sfiles = os.environ["SETUP_SHORTCUTS"].split(":") shortcuts = {} for name in sfiles: sfile = os.path.abspath(name) if not os.path.exists(sfile): if hasattr(gvars, 'out'): gvars.out.put("Unable to open %s. Ignoring" % sfile,setup_globals.WARN) else: shortcuts.update(getShortcutDict(sfile)) return shortcuts
[docs]def expandShortcuts(args,RecLimit=255): """Expand all shortcuts specified in args. No more than RecLimit expansions should be required. This limit can be used to detect circular references""" ans = [] count = RecLimit gvars.shortcuts = getShortcuts() shortcuts = gvars.shortcuts while args: scut = args[0] del args[0] if scut[0] != setup_globals.SHORTCUT_CHAR: ans.append(scut) else: # found a shortcut cand = [] # find a shortcut starting with given letters (case insensitive) for x in shortcuts.keys(): y = x.lower() if y.startswith(scut[1:].lower()): cand.append(x) if len(cand) == 1: scut = cand[0] # only one candidate elif shortcuts.has_key(scut[1:].lower()): # specified key as such exists scut = scut[1:].lower() # pick given key # now process the shortcut if not shortcuts.has_key(scut): # invalid shortcut gvars.out.put("\n***WARNING*** Ignoring unknown shortcut %s while expanding %s.\n" % (scut," ".join(args)),setup_globals.IMPINFO) elif count > 0: count = count - 1 args[0:0] = shortcuts[scut] # insert expansion of shortcut in front of args else: raise SetupError("Too many shortcuts. Circular reference?") return ans
[docs]def setSetupVars(strlist): """Given a list of strings. Identifies those of the form A=B and updates gvars.setup_vars. Returns unprocessed list of strings""" ans = [] # declare setup variables for all top level units # these are boolean variables which decide whether # to include this unit or not for x in gvars.topUnitNames: # by default do not include any units gvars.setup_vars.addunit(x,False) for opt in strlist: p = opt.find("=") if p < 0: # no equal found ans.append(opt) else: gvars.setup_vars.set(opt[:p],opt[p+1:]) # set variable to value return ans
[docs]def custom_getopt(longoptions): """Parse command line arguments, working in gnu mode using only longoptions. GNU MODE = allow non-option arguments to be followed by options. We also allow user to use shortcuts as well as define variables like make""" max_shortcuts = 255 # no more than 255 shortcuts allowed per invocation optvallist = [] rest = [] toparse = cleanupCommandLine(ADDL_DEF_ARGS+sys.argv[1:]) # double "-" to "--" fulllist = expandShortcuts(toparse) # expand the shortcuts fullCmdList = [x for x in fulllist if x and (x[0] == "-" or x.find("=") < 1) ] # remove non-options with "=" in it gvars.fullCmdLine = " ".join(fullCmdList) # this gets printed toparse = fulllist[:] # make a copy of the list while toparse: optval_sublist, toparse = getopt.getopt(toparse,"",longoptions) optvallist.extend(optval_sublist) if toparse: badoption = toparse[0] del toparse[0] rest.append(badoption) return (fulllist,optvallist,setSetupVars(rest))
def parseCommandLine(): # process all the options # those requiring arguments suffixed with = longopts = WITHOUT_ARGS + [x+"=" for x in WITH_ARGS] try: (fullcmdline,optvallist,rest) = custom_getopt(longopts) except getopt.GetoptError,e: gvars.out.put(str(e),setup_globals.ERROR) usage() # print usage info # Not given any program name if not rest: usage() # if given many the last one wins if len(rest) > 1: gvars.out.put(" WARNING: Multiple problem names given. winner="+rest[-1],setup_globals.WARN) gvars.simulation_name = rest[-1] # store program name # Find the approrpiate simualtion directory # a little tricky to enable project_simulations_dir sim_dir = search_paths(gvars.simulations_path, gvars.simulation_name) if not sim_dir.startswith(gvars.project_simulations_dir): sim_dir = [os.path.relpath(sim_dir, sp) for sp in gvars.source_path if sim_dir.startswith(sp)][0] gvars.simulation_dir = sim_dir # all acceptable values for "--verbose" keyword vrblevels = {"DEBUG":setup_globals.DEBUG, "PPDEBUG":setup_globals.PPDEBUG, "PPWARN":setup_globals.PPWARN, "WARN":setup_globals.WARN, "INFO":setup_globals.INFO, "IMPINFO":setup_globals.IMPINFO, "ERROR":setup_globals.ERROR} # all acceptable values for "--gridinterpolation" keyword allGridInterpolations = {"MONOTONIC":setup_globals.GRID_INTERP_MONOTONIC, "NATIVE":setup_globals.GRID_INTERP_NATIVE} # all acceptable values for "--geometry" keyword allGeometries = {"CARTESIAN":setup_globals.GRID_GEOM_CARTESIAN, "CYLINDRICAL":setup_globals.GRID_GEOM_CYLINDRICAL, "SPHERICAL":setup_globals.GRID_GEOM_SPHERICAL, "POLAR":setup_globals.GRID_GEOM_POLAR} withUnits = {} # dictionary to store list of units to add (prevents duplicate entries) for (arg,val) in optvallist: if arg == '--portable': gvars.portable = 1 elif arg == '--noclobber': gvars.noClobber = 1 elif arg == '--auto': gvars.auto = 1 elif arg == '--datafiles': gvars.datafiles.append(val) elif arg == '--parfile': gvars.parfile = val elif arg == '--debug': gvars.buildFlag = "DEBUG" elif arg == '--test': gvars.buildFlag = "TEST" elif arg == '--opt': gvars.buildFlag = "OPT" elif arg == '--maxblocks': gvars.maxblocks = int(val) elif arg == '--makehide': gvars.makedisplay = 0 elif arg == '--makefile': gvars.makefileext = "."+val elif arg == '--nxb': gvars.nxb = int(val) elif arg == '--nyb': gvars.nyb = int(val) elif arg == '--nzb': gvars.nzb = int(val) elif arg == '--site': gvars.build_site = val elif arg == '--tau': gvars.build_tau = val elif arg == '--ostype': gvars.build_os = val elif arg == '--objdir': gvars.project_build_dir = val elif arg == '--rundir': gvars.rundir = val elif arg == '--help': usage() elif arg == '--unitsfile': gvars.unitsfile = val elif arg == '--fbs': gvars.setup_vars.set("fixedBlockSize",True) elif arg == '--nofbs': gvars.setup_vars.set("fixedBlockSize", False) elif arg == '--strictparams': gvars.strictParams = 1 # DEV 'curvilinear' # * originally used to have the same effect as -gridinterpolation=monotonic # does now, in addition to #defining GRID_CURVILINEAR 1 in Flash.h. # * Then there came a time when # o -curvilinear was deprecated, and # o -gridinterpolation=monotonic had the effect of always #defining # GRID_CURVILINEAR 1 in Flash.h. # * Now the time has come when # o -gridinterpolation=monotonic does NOT automatically #define GRID_CURVILINEAR; # o (but -geometry={cylindrical,spherical,polar} still does;) # o -geometry={cylindrical,spherical,polar} implies -gridinterpolation=monotonic; # o -curvilinear is not deprecated any more, since it can be used to force # #defining GRID_CURVILINEAR 1 in Flash.h when this is not automatically # done any more. That is, -curvilinear can be useful (and has only an effect) # when -geometry={cylindrical,spherical,polar} is not requested. # deprecated with introduction of 'gridinterpolation' (below) # DEV 'curvilinear' now deprecated with introduction of 'gridinterpolation' (below) elif arg == '--curvilinear': gvars.out.put("\n***************************** INFO *********************************\n" + "The -curvilinear flag is nearly always unnecessary.\n" + "Use --gridinterpolation={cylindrical,spherical,polar} to configure\n" + "FLASH for a specific non-Cartesian geometry.\n" + "(These flags are not needed at all when using PARAMESH in LIBRARY\n" + "MODE, i.e., ParameshLibraryMode=True, or when using Paramesh4dev.)\n" + "********************************************************************\n",setup_globals.WARN) gvars.curvilinear = 1 elif arg in ["--1d","--2d","--3d"]: gvars.dimension = int(arg[2]) # i.e. 1 or 2 or 3 gvars.setup_vars.set("nDim",gvars.dimension) elif arg == "--index-reorder": gvars.setup_vars.set("GridIndexReordered",True) # for use in Config file gvars.indexReorder = True # for use in Makefile gvars.defines.append("-DINDEXREORDER") # for use in code elif arg in ["--with-unit","--unit"]: if val.endswith(os.sep): val = val[:-1] if val.startswith("source"+os.sep): val = val[7:] withUnits[val] = 1 gvars.setup_vars.addunit(val,True) # set corresponding setup var to true elif arg == "--without-unit": # remove all units added which come under specified unit # also add to list of units to be ignored when handling REQUESTS keyword if val.endswith(os.sep): val = val[:-1] rmlist = [x for x in withUnits.keys() if x == val or x.startswith(val+os.sep)] for x in rmlist: del withUnits[x] gvars.withoutUnits[val] = 1 elif arg == "--kill-unit": gvars.killUnits[val] = 1 elif arg in ["--with-library","--library"]: if not val: continue # no name given --> ignore parts = val.split(",") libname = parts[0] args = string.join(parts[1:]," ") # replace commas with space if len(args) >= 2 and args[0] == args[-1] and args[0] in ['"',"'"]: # argument has been quoted args = args[1:-1] gvars.with_libraries[libname.lower()] = args elif arg == "--without-library": val = val.lower() if gvars.with_libraries.has_key(val): del gvars.with_libraries[val] gvars.withoutLibraries[val] = 1 elif arg == '--verbose': # set verbosity level if not val: continue # no argument dont change level if vrblevels.has_key(val.upper()): gvars.verbose = vrblevels[val.upper()] else: gvars.out.put("Unrecognized verbosity level [%s]" % val,setup_globals.ERROR) usage() elif arg == '--gridinterpolation': # set grid interpolation if not val: continue # no argument; don't change interpolation if allGridInterpolations.has_key(val.upper()): gvars.gridInterpolation = allGridInterpolations[val.upper()] else: gvars.out.put("Unrecognized grid interpolation [%s]" % val, setup_globals.ERROR) usage() elif arg == '--geometry': # set geometry if not val: continue # no argument; don't change geom if allGeometries.has_key(val.upper()): gvars.gridGeometry = allGeometries[val.upper()] if val.upper() != "CARTESIAN": # All geometries other than cartesian (i.e. cylindrical, # spherical, and polar) are automatically curvilinear. # (See note above on -curvilinear.) gvars.curvilinear = 1 else: gvars.out.put("Unrecognized geometry [%s]" % val, setup_globals.ERROR) usage() elif arg == "--defines": # declare additional CPP/FPP stuff if not val: # kill existing defines gvars.defines=[] continue for x in val.split(","): x = x.strip() p = x.find("=") if p < 0: # no = so just a flag name = x val = None else: name = x[:p] val = x[p+1:].strip() if val: gvars.defines.append("-D%s=%s" % (name.upper(),val)) else: gvars.defines.append("-D%s" % name.upper()) elif arg == "--particlemethods": keywordParticleType = "TYPE" keywordOverrideList = ["INIT","MAP","ADV"] nameValuePairs = [] particleType = "" for x in val.split(","): x = x.strip() p = x.find("=") if p < 0: # We require keywords and associated values. raise SetupError("particlemethods option: must contain 'keyword=value' pairs!") else: name = x[:p] val = x[p+1:].strip() if (name.upper() == keywordParticleType): particleType = val[:].upper() else: #Only add the name,value pair if it is an option #we can override. if name.upper() in keywordOverrideList: nameValuePairs.append((name.upper(),val.upper())) else: raise SetupError("particlemethods option: keyword '%s' no recognized!" % name) if (particleType != ""): gvars.particleMethods[particleType] = nameValuePairs else: raise SetupError("particlemethods option: must specify a particle type with TYPE=<name of particle type>!") else: if not val: a = arg else: a = "%s=%s" % (arg,val) gvars.out.put('Invalid Option: %s' % a,setup_globals.ERROR) usage() # takes care of duplicate --with-unit=X arguments gvars.withUnits = withUnits.keys() # inform gvars.out about the verbosity level gvars.out.debuglevel = gvars.verbose # Perform basic checks on user options def checkOpts(): if gvars.auto and gvars.unitsfile: raise SetupError("-unitsfile cannot be used with -auto") if ((gvars.gridInterpolation == setup_globals.GRID_INTERP_NATIVE) and (gvars.gridGeometry == setup_globals.GRID_GEOM_CYLINDRICAL or gvars.gridGeometry == setup_globals.GRID_GEOM_SPHERICAL or gvars.gridGeometry == setup_globals.GRID_GEOM_POLAR)): raise SetupError("Native Grid interpolation may not be used with %s" % gvars.gridGeometry) if gvars.dimension < 3: if gvars.nzb != None: raise SetupError("Must not specify nzb for dimensionality < 3d") if gvars.dimension < 2: if gvars.nyb != None: raise SetupError("Must not specify nyb for dimensionality < 2d") # finalize all the options made # this is called after unit_list.adjust_opts() def finalizeOpts(): if gvars.nzb == None: if gvars.dimension > 2: gvars.nzb = 8 else: gvars.nzb = 1 if gvars.nyb == None: if gvars.dimension > 1: gvars.nyb = 8 else: gvars.nyb = 1 if gvars.nxb == None: gvars.nxb = 8 defines = {} defines["N_DIM"] = gvars.dimension defines["MAXBLOCKS"] = gvars.maxblocks defines["NXB"] = gvars.nxb defines["NYB"] = gvars.nyb defines["NZB"] = gvars.nzb gvars.setup_vars.set("nxb",gvars.nxb) gvars.setup_vars.set("nyb",gvars.nyb) gvars.setup_vars.set("nzb",gvars.nzb) gvars.setup_vars.set("maxBlocks",gvars.maxblocks) ## if gvars.setup_vars.get("ParameshLibraryMode"): ## defines["LIBRARY"] = None ditems = defines.items() ditems.sort() for (k,v) in ditems: if v: gvars.defines.append("-D%s=%s"% (k,v)) else: gvars.defines.append("-D%s"% k) # if old defines file exists, check if new defines conflict with old one newDefines = None # the defines have not changed #od = os.path.join(gvars.flash_src_dir,gvars.project_build_dir) od = os.path.join(gvars.flash_src_dir, gvars.project_setup_dir) sd = os.path.join(od,setup_globals.SETUP_DEFINES_FILENAME) if not os.path.isdir(od): os.makedirs(od) f = LazyFile(sd) for a in gvars.defines: f.write(a+"\n") f.close() newDefines = not f.samefile # if defines changed and we wanted noClobber if newDefines and gvars.noClobber == 1: gvars.out.put("Compile Time Parameters changed since last run. Ignoring noclobber",setup_globals.WARN) gvars.noClobber = 0 ################################## External Interface ################################3 def parse(): parseCommandLine() checkOpts() def final(): finalizeOpts() def write_cmd_line(): #file = open(os.path.join(gvars.flash_src_dir, gvars.project_build_dir, setup_globals.SETUP_CALL_FILENAME), 'w') file = open(os.path.join(gvars.project_setup_dir, setup_globals.SETUP_CALL_FILENAME), 'w') for arg in sys.argv: file.write(arg+' ') file.write('\n') file.write('\nExpanded Command line\n') file.write('%s\n' % gvars.fullCmdLine) file.write('\nDefined Setup Variables:\n\n') gvars.setup_vars.printvars(file,ignoreprefix="with") file.close()