import os
import re
from warnings import warn
# relative imports needed!
from ..dsl.configuration import Configuration, ConfigurationUnion
from . import setup_globals
from .setup_globals import gvars, SetupError
from .utils import search_paths
from .rp_info import RPInfo
from .var_info import VarInfo
from .template import Template
#
# Configuration List
#
[docs]class ConfigurationList(object):
"""Declares a class ConfigurationtList which contains a list of unit names
together with methods to manipulate them. This must be aware of how the
problem is being setup.
"""
def __init__(self, ignore_pp=False):
self.units = {} # dictionary mapping name to FlashUnit object
self.ignore_pp = ignore_pp
def check_empty(self):
# programming error
if self.units:
gvars.out.put("Programming Error: self.units should be empty here",
setup_globals.ERROR)
raise SetupError
[docs] def remove_units(self, unitnames):
"""Remove these units also
returns the number of units actually removed"""
if isinstance(unitnames, basestring):
unitnames = [unitnames]
count = 0
for unitname in unitnames:
if not unitname:
continue
if unitname in self.units:
count += 1
del self.units[unitname]
return count
[docs] def remove_subtrees(self, unitnames):
"""remove these units and all their children"""
# speed up common case
if not unitnames:
return
rmunitnames = []
for unitname in unitnames:
if unitname.endswith(os.sep):
rmunitnames.append(unitname[:-1])
else:
rmunitnames.append(unitname)
# rmunitnames has all unitnames not ending with "/"
rmlist = [] # names of units to be removed
for unitname in rmunitnames:
usep = unitname + os.sep
for uname in self.units.keys():
if uname == unitname or uname.startswith(usep):
rmlist.append(uname)
for uname in rmlist:
del self.units[uname]
[docs] def add_units(self, unitnames, comment=""):
"""Add these units and returns the number of units actually added."""
if isinstance(unitnames, basestring):
unitnames = [unitnames]
count = 0
for unitname in unitnames:
if 0 == len(unitname):
continue
if unitname in self.units:
continue
source_abspath = [os.path.abspath(sd) for sd in gvars.source_path]
if os.path.isabs(unitname) and unitname in source_abspath:
continue
if count == 0 and comment:
gvars.out.put(comment, setup_globals.INFO)
gvars.out.push()
count += 1
if comment:
gvars.out.put(unitname, setup_globals.IMPINFO)
top_unit = (unitname in gvars.topUnitNames)
# find and add unit
name = os.path.normpath(unitname) # something like 'IO/common/hdf5/'
name_path = name if name.startswith(gvars.project_simulations_dir) \
else search_paths(gvars.source_path, name)
name_abspath = os.path.abspath(name_path)
if not os.path.isdir(name_abspath):
raise SetupError('Unit {0} not found (at {1})'.format(name, name_abspath))
conf_names = ['config.py', 'Config.py', 'Config']
confs_present = [f for f in os.listdir(name_abspath) if f in conf_names]
config_filename = None if 0 == len(confs_present) \
else os.path.join(name_abspath, confs_present[0])
#if config_filename is None:
# continue
if config_filename is not None and config_filename.endswith('.py'):
# FIXME do something special to handle python config files
conf = None
else:
conf = Configuration(config_filename, top_unit=top_unit, unitname=name,
usevars=gvars.setup_vars.vars, ignore_pp=self.ignore_pp,
without_units=gvars.withoutUnits, unitpath=name_abspath)
self.units[unitname] = conf
if count > 0 and comment:
gvars.out.pop()
return count
def check_top_units(self):
for top_unit in gvars.topUnitNames:
if top_unit not in self.units:
continue
init_file = os.path.basename(top_unit) + "_init.F90"
if not os.path.isfile(os.path.join(self.units[top_unit].filename, init_file)):
msg = ("WARNING: Missing 'init' File\n"
"Each API-level unit directory must "
"directly contain an initialization file\n"
'whose name matches the name of that directory plus "_init.F90"\n'
'The directory "{0}" does not contain a file "{1}"')
msg = msg.format(top_unit, init_file)
warn(msg, RuntimeWarning)
def add_top_units(self):
self.add_units(gvars.topUnitNames)
[docs] def check_suggest(self):
"""list of units which have been suggested but not included."""
badunits = []
unames = self.units.keys()
for uname in unames:
for suglist in self.units[uname].suggest:
badlist = 1
for sug in suglist:
if sug in unames:
badlist = None
# append the alternatives
if badlist:
badunits.append((uname, suglist))
# some suggestion not taken
if badunits:
gvars.out.put("\nIGNORED SUGGESTIONS", setup_globals.IMPINFO)
for (uname, suglist) in badunits:
gvars.out.put("{0} suggested one of the following units as well: ".format(uname),
setup_globals.IMPINFO)
gvars.out.push()
for sug in suglist:
gvars.out.put(sug, setup_globals.IMPINFO)
gvars.out.pop()
gvars.out.put("", setup_globals.IMPINFO)
def check_requirements(self):
for unit in self.units.values():
# will be a list of lists
# each member of this list-within-a-list will represent
# a series of alternative Units as specified in a Config
# file by the syntax "REQUIRES A OR B OR C".
sets_of_alternatives = unit.requires
for set_of_alternatives in sets_of_alternatives:
for unit_name in set_of_alternatives:
if unit_name in self.units:
# We have one in the list of required units
# so don't bother checking the others
break
else:
raise SetupError('{0} REQUIRES {1}, not included'.format(unit.name,
" or ".join(set_of_alternatives)))
def check_exclusivity(self):
gvars.out.put("Checking if Exclusive units are included", setup_globals.DEBUG)
# units contains everybody's parents
for unit in self.units.values():
for group in unit.exclusive:
# No two elements of group must be in units
a = None
for b in group:
if b not in self.units:
continue
if a:
raise SetupError('{0} and {1} are exclusive'.format(a, b))
a = b
def check_conflicts(self):
gvars.out.put("Checking for Conflicting units", setup_globals.DEBUG)
for unit in self.units.values():
for b in unit.conflicts:
if b in self.units:
raise SetupError("setup Error: requested unit "
"{0} CONFLICTS with {1}".format(b, unit))
def get_unit_names_from_file(self, file):
if not os.path.isfile(file):
gvars.out.put('cannot access {0} file'.format(file), setup_globals.ERROR)
gvars.out.push()
gvars.out.put('* Either use the -auto option or', setup_globals.ERROR)
gvars.out.put('* specify the Units file using the -unitsfile=<filename> option',
setup_globals.ERROR)
gvars.out.pop()
raise SetupError('No Units file found', "NOUNITS")
gvars.out.put('scanning {0} file for included units'.format(file), setup_globals.IMPINFO)
ans = []
for line in open(file).readlines():
rawline = line
if line.count('#'):
line = line[:line.find('#')]
line = line.strip()
if not line:
continue
try:
a, b = line.split()
if a != 'INCLUDE':
raise SetupError
except (ValueError, SetupError):
raise SetupError('Bad syntax:\n' + rawline)
ans.append(b)
return ans
def add_units_from_file(self):
fname = os.path.join(gvars.project_setup_dir, setup_globals.UNITS_FILENAME)
self.add_units(self.get_unit_names_from_file(fname), "Scanning Units file")
[docs] def get_default_units(self):
"""return names of default units of units already present"""
return [unit.default for unit in self.units.values()]
[docs] def add_default_units(self):
"""add default units of all units"""
while self.add_units(self.get_default_units(), "") > 0:
pass
[docs] def add_kernel_units(self):
"""check to see which units are Kernel units
if we have a Kernel unit then we want to
include all units and directories under the
unit specified to be a Kernel
"""
ans = []
gvars.out.push()
gvars.out.put('*** KERNEL *** add_kernel_units *** START ***', setup_globals.DEBUG)
for unit in self.units.values():
if unit.kernel:
gvars.out.put('Processing KERNEL for {0}'.format(unit), setup_globals.DEBUG)
gvars.out.push()
if not os.path.isdir(unit.kernel):
msg = "Invalid KERNEL {0}, not a directory, requested by {1}.\n"
msg = msg.format(unit.kernel, unit)
raise SetupError(msg)
gvars.out.pop()
ans.extend(self.recursive_get_dir(unit.kernel))
self.add_units(ans)
gvars.out.put('*** KERNEL *** add_kernel_units *** END ***', setup_globals.DEBUG)
gvars.out.pop()
[docs] def add_grid_interpolation(self):
"""Different interpolation units need to be added depending on which
Grid has been chosen. This is a somewhat hacky solution to that
problem. As far as I know this is the only instance of a command-
line option whose effect depends on which other Units have already
been included. -nttaylor
"""
# Note that no interpolation Unit needs to be added for UG
ans = []
if gvars.gridInterpolation == setup_globals.GRID_INTERP_MONOTONIC:
for unit_name in self.units.keys():
if unit_name.startswith("Grid/GridMain/paramesh/paramesh4"):
# Check if added this already
for unit_name2 in self.units.keys():
if unit_name2.startswith("Grid/GridMain/paramesh/interpolation/Paramesh4"):
break
else:
# add the required interpolation unit
ans.append("Grid/GridMain/paramesh/interpolation/Paramesh4")
break
elif unit_name.startswith("Grid/GridMain/paramesh/Paramesh2"):
# Check if added this already
for unit_name2 in self.units.keys():
if unit_name2.startswith("Grid/GridMain/paramesh/Paramesh2/monotonic"):
break
else:
# add the required interpolation unit
ans.append("Grid/GridMain/paramesh/Paramesh2/monotonic")
break
elif gvars.gridInterpolation == setup_globals.GRID_INTERP_NATIVE:
# This is the only other possiblity, and all it means is that we
# don't have to add any special units, so there's nothing to do.
pass
self.add_units(ans)
def recursive_get_dir(self, path):
def vfunc(ans, dname, fnames):
gvars.out.put('...while walking, ans='
'{0}, dname="{1}", fnames={1} ...'.format(ans, dname, fnames),
setup_globals.DEBUG)
dont_descend = []
# remove all (a) ".files" and (b) non-directories from fnames
for x in fnames:
if x[0] == ".":
# names starting with . to be ignored
dont_descend.append(x)
continue
jname = os.path.join(dname, x)
if not os.path.isdir(jname):
# not a directory, also ignored
dont_descend.append(x)
continue
# removal in place so recursion does not go there
for x in dont_descend:
fnames.remove(x)
# if we descended into this dname directory, append it to answer list
ans.append(dname)
ans = []
gvars.out.put('Will walk {0} ...'.format(path), setup_globals.DEBUG)
os.path.walk(path, vfunc, ans)
# now ans contains the list of all directories inside path
# except "." directories and their children
gvars.out.put('...and found {1} by walking.'.format(ans), setup_globals.DEBUG)
return ans
def parent_units(self):
return [unit.parent() for unit in self.units.values()]
def add_parent_units(self):
while self.add_units(self.parent_units()) > 0:
pass
def remove_parent_units(self):
self.remove_units(self.parent_units())
[docs] def get_required_units(self):
"""list of unitnames to be added"""
ans = []
for unit in self.units.values():
# will be a list of lists
# each member of this list-within-a-list will represent
# a series of alternative Units as specified in a Config
# file by the syntax "REQUIRES A OR B OR C". Only one of
# these units need be appended to 'ans'
sets_of_alternatives = unit.requires
for set_of_alternatives in sets_of_alternatives:
for unit_name in set_of_alternatives:
if unit_name in self.units:
# we already have one in the list of required units
# so don't bother checking the others
break
else:
# only if we didn't have any of the listed alternatives
# do we choose the first one by appending it to 'ans'
ans.append(set_of_alternatives[0])
return ans
[docs] def add_required_units(self):
"""Satisfy requirements"""
while self.add_units(self.get_required_units()) > 0:
pass
[docs] def write_units_file(self):
"""Disable old method of object dir creation, write to current dir"""
outfile = os.path.join(gvars.project_setup_dir, setup_globals.UNITS_FILENAME)
if os.path.isfile(outfile):
gvars.out.push()
gvars.out.put('Backing up {0}'.format(outfile), setup_globals.INFO)
os.rename(outfile, outfile + '.bak')
gvars.out.pop()
outfd = open(outfile, 'w')
outfd.write('#Units file for {0} generated by setup \n\n'.format(gvars.simulation_name))
# Dont print parent units (makes file concise)
p_units = self.parent_units()
c_units = [x for x in self.units.keys() if x not in p_units]
c_units.sort()
for unitname in c_units:
outfd.write('INCLUDE {0}\n'.format(unitname))
outfd.close()
#
# User calls methods below
#
def get_list(self):
list = self.units.keys()
list.sort()
return list
def get_link_order(self):
sim_root_dir = setup_globals.SIM_SETUP_DIR.split("/")[0]
def earlier(corder, childa, childb):
"""Return true if child "unita" should be linked earlier"""
# code comes here only if we have a non-trivial corder
if childa in corder:
try:
return cmp(corder.index(childa), corder.index(childb))
except:
# unitb is not in the list
return -1
else:
# unita not present in list
if childb in corder:
return 1
else:
# both not in corder
return cmp(childa, childb)
def defcmp(childa, childb):
"""default comparison between different children"""
# Push simulations to the end
if childa == sim_root_dir:
return 1
if childb == sim_root_dir:
return -1
# normal compare
return cmp(childa, childb)
def apply_aliases(apath):
ap = "/".join(apath)
apaths = [ap.replace(k, v) for k, v in gvars.unit_aliases.items()
if ap.startswith(k)]
if len(apaths) == 0:
return apath
elif len(apaths) == 1:
return apaths[0].split('/')
else:
raise ValueError("Too many matching aliases for {0}: {1}".format(ap, apaths))
def compare(apath, bpath):
"""return 0 if equal, -1 if patha < pathb, 1 if patha > pathb"""
if apath == bpath:
return 0
# Apply aliases for comparisons
apath = apply_aliases(apath)
bpath = apply_aliases(bpath)
# find youngest common ancestor
common = []
patha = apath[:] # copy is essential here
pathb = bpath[:]
while patha and pathb and (patha[0] == pathb[0]):
common.append(patha[0])
del patha[0]
del pathb[0]
parent = "/".join(common) # found youngest common parent
# patha is a prefix of pathb
if not patha:
return -1
# pathb is a prefix of patha
if not pathb:
return 1
# Now need to compare childa and childb according to order specified by parent
childa = patha[0]
childb = pathb[0]
# if trouble accessing parent's order (pick default ordering)
try:
corder = self.units[parent].childorder
if corder:
return earlier(corder, childa, childb)
else:
return defcmp(childa, childb)
except:
return defcmp(childa, childb)
# returns names of units present in a fixed order
# split unitnames into list describing path
pathlist = [unitname.split("/") for unitname in self.units.keys()]
# First do a lexicographic sort as that should get most of elements in place
# since this is optimized in python, we have done most of the work without using
# our fancy ordering
pathlist.sort()
# now use our fancy sorting routine, so hopefully there are few calls to our
# comparator algorithm
pathlist.sort(compare)
# combine paths back to strings
pl = ["/".join(x) for x in pathlist] # contract paths to unitnames
return pl
[docs] def get_config_info(self, **kw):
"""Generate FlashUnitUnion class based on given units"""
cinfo = ConfigurationUnion(self.units.values(), **kw)
cinfo.unit_names = self.get_list()
return cinfo
[docs] def generate_units_file(self):
"""called only when '-auto' flag is passed"""
gvars.out.put('generating default Units file', setup_globals.IMPINFO)
self.check_empty()
# add the appropriate unit from simulation
self.add_units(gvars.simulation_dir)
if gvars.simulation_dir.startswith(gvars.project_simulations_dir):
# if in a local simultion dir, we must manually add the SimulationMain unit
self.add_units(setup_globals.SIM_SETUP_DIR)
# add units specified on command-line with "--with-unit"
self.add_units(gvars.withUnits)
while True:
oldnames = self.get_list() # names of all units in this FlashUnitList instance
self.add_parent_units()
self.add_required_units()
self.remove_parent_units()
# start over if we added any required units
if oldnames != self.get_list():
continue
self.add_default_units()
self.add_kernel_units()
self.add_grid_interpolation()
# Nothing new added so we are done
if oldnames == self.get_list():
break
# now kill units
if gvars.killUnits:
gvars.out.put('Killing subtrees: {0}'.format(
",".join(gvars.killUnits.keys())),
setup_globals.INFO) # USER BEWARE
self.remove_subtrees(gvars.killUnits.keys())
# Tell User about the list of units
gvars.out.push()
for unitname in self.get_list():
gvars.out.put(unitname, setup_globals.IMPINFO)
gvars.out.pop()
self.write_units_file()
# If user had not used "-auto", we would not even be in this branch
# of code, so now that the Units file is written, we clear out the
# units dictionary again. Now we are in the same state regardless of
# whether the "-auto" flag was passed or not. The "Units" file must
# be read in by "add_units_from_file" in method "populate" below.
self.units = {}
def populate(self):
# main stuff
self.check_empty()
sim_unit = [gvars.simulation_dir]
# read Units file and add units found there
self.add_units_from_file()
if not gvars.auto:
# check if a Simulation is already present
names = [x for x in self.get_list() if \
any([x.startswith(path) for path in gvars.simulations_path])]
try:
# remove unit if present
names.remove(sim_unit)
except ValueError:
pass
if names:
gvars.out.put("\nERROR: Multiple Simulation Units Found", setup_globals.ERROR)
gvars.out.push()
gvars.out.put("You tried to setup {0} as well as ".format(sim_unit),
setup_globals.ERROR)
gvars.out.put("use your previous (or specified) Units file.", setup_globals.ERROR)
gvars.out.put("Your units file already has "
"{0}. Your choices are \n".format(names[0]), setup_globals.ERROR)
gvars.out.put("* Use the -auto option and I will use my crystal ball",
setup_globals.ERROR)
gvars.out.put("* Explicitly specify the units file using -unitsfile option",
setup_globals.ERROR)
gvars.out.put("* Change the problem you want to setup", setup_globals.ERROR)
gvars.out.pop()
raise SetupError("")
else:
self.add_units(sim_unit)
gvars.out.put('checking for default sub-units in included units', setup_globals.INFO)
self.add_default_units()
self.add_parent_units()
self.add_kernel_units()
gvars.out.put('checking for exclusivity and conflicts', setup_globals.INFO)
self.check_exclusivity()
self.check_conflicts()
gvars.out.put('looking for paths of non-included units', setup_globals.INFO)
self.check_top_units()
self.add_top_units()
self.add_units(sim_unit)
gvars.out.put('checking requirements', setup_globals.INFO)
self.check_requirements()
self.check_suggest()
# remove specified units and children (USER BEWARE no CHECK performed on these)
self.remove_subtrees(gvars.killUnits.keys())
def get_rp_info(self, max_plot_vars, **kw):
rp_info = RPInfo(**kw)
for (unitname, unit) in self.units.items():
for (rpname, (rptype, rpvalue, rpconst, rprange)) in unit.parameter.items():
# try rpname, then rpname_parameter
rpcomment = unit.d.get(rpname, unit.d.get("{0}_parameter".format(rpname), ""))
rp_info.addRP(rpname, type=rptype, value=rpvalue, const=rpconst, range=rprange,
location=unitname, comment=rpcomment)
# now for all documentation without corresponding parameter declarations
# which start with __
for (key, value) in unit.d.items():
if key[:2] == '__' and key not in unit.parameter:
# a type of DOC is for documentation only
rp_info.addRP(key, type='DOC', location=unitname, comment=value)
# Generate enough plot_var_N names for all variables in the simulation.
if type(max_plot_vars) == type(1):
numRegularPlotVars = max_plot_vars
for i in range(1, numRegularPlotVars + 1):
rp_info.addRP('plot_var_{0}'.format(i), type="STRING", value='"none"',
location="IO/IOMain", comment="(automatically generated by setup)")
else:
rp_info.addRP('plot_var_{0}'.format(max_plot_vars), type="STRING", value='"none"',
location="IO/IOMain", comment="(automatically generated by setup)")
return rp_info
def get_var_info(self, **kw):
var_info = VarInfo(**kw)
for (unitname, unit) in self.units.items():
# Add all variables
for (var, (attr, eos1, eos2)) in unit.variable.items():
var = var.lower()
varcomment = unit.d.get("{0}_variable".format(var), "")
var_info.addVar(var, type="Variable", location=unitname,
attribs=attr, comment=varcomment)
# Add all particle properties
for (var, attr) in unit.particleprop.items():
varcomment = unit.d.get("{0}_particleprop".format(var), "")
var_info.addVar(var, type="Particle Property", location=unitname,
attribs=[attr], comment=varcomment)
# Add all particle types
for var in unit.particletype.keys():
varcomment = unit.d.get("{0}_particletype".format(var), "")
var_info.addVar(var, type="Particle Type", location=unitname,
attribs=[], comment=varcomment)
# Add all particle property -> grid var maps
for (var, attr) in unit.particlemap.items():
var_info.addVar(var, type="Particle Property Map",
location=unitname, attribs=[attr])
# Add all species
for var in unit.species.keys():
varcomment = unit.d.get("{0}_species".format(var), "")
var_info.addVar(var, type="Species", location=unitname,
attribs=[], comment=varcomment)
# Add all face variables
for var in unit.facevar.keys():
varcomment = unit.d.get("{0}_facevar".format(var), "")
var_info.addVar(var, type="Face Variable", location=unitname,
attribs=[], comment=varcomment)
# Add all scratch variables
for var in unit.scratchvar.keys():
varcomment = unit.d.get("{0}_scratchvar".format(var), "")
var_info.addVar(var, type="Scratch Variable", location=unitname,
attribs=[], comment=varcomment)
for var in unit.scratchcentervar.keys():
varcomment = unit.d.get("{0}_scratchcentervar".format(var), "")
var_info.addVar(var, type="Scratch Center Variable", location=unitname,
attribs=[], comment=varcomment)
for var in unit.scratchfacexvar.keys():
varcomment = unit.d.get("{0}_scratchfacexvar".format(var), "")
var_info.addVar(var, type="Scratch Face-X Variable", location=unitname,
attribs=[], comment=varcomment)
for var in unit.scratchfaceyvar.keys():
varcomment = unit.d.get("{0}_scratchfaceyvar".format(var), "")
var_info.addVar(var, type="Scratch Face-Y Variable", location=unitname,
attribs=[], comment=varcomment)
for var in unit.scratchfacezvar.keys():
varcomment = unit.d.get("{0}_scratchfacezvar".format(var), "")
var_info.addVar(var, type="Scratch Face-Z Variable", location=unitname,
attribs=[], comment=varcomment)
# Add all Mass Scalars
for var in unit.mass_scalar.keys():
varcomment = unit.d.get("{0}_mass_scalar".format(var), "")
var_info.addVar(var, type="Mass Scalar", location=unitname,
attribs=[], comment=varcomment)
# Add all Fluxes
for var in unit.flux.keys():
varcomment = unit.d.get("{0}_flux".format(var), "")
var_info.addVar(var, type="Flux", location=unitname,
attribs=[], comment=varcomment)
return var_info
[docs] def adjust_opts(self):
"""set default values for options possibly based of list of units we are using"""
gvars.out.put("Computing default values for options not specified on command line",
setup_globals.IMPINFO)
# Find all Grid related units we have now
gp = setup_globals.GRID_PREFIX
if not gp.endswith(os.sep):
gp = gp + os.sep
gridList = [x[len(gp):] for x in self.get_list() if x.startswith(gp) and x[len(gp):]]
# now gridList also includes non Grid subunits of "Grid/GridMain"
# eliminate choices which do not occur in GRID_CHOICES
grids = {}
for x in gridList:
# mark grids we have
fp = x.split(os.sep)[0]
if fp in setup_globals.GRID_CHOICES:
grids[fp] = 1
if not grids:
gvars.out.put("No Grid specified/found", setup_globals.WARN)
grid = ""
elif len(grids) == 1:
grid = grids.keys()[0]
gvars.out.put("Using Grid {0}".format(grid), setup_globals.INFO)
else:
raise SetupError("Found multiple grids {0}!".format(str(grids.keys())))
# Adjust maxblocks
if gvars.maxblocks == None:
# using UG
if grid == 'UG':
gvars.maxblocks = 1
elif grid == 'paramesh':
# using paramesh
if gvars.dimension == 3:
gvars.maxblocks = 200
else:
gvars.maxblocks = 1000
else:
# some other grid package
if gvars.dimension == 3:
gvars.maxblocks = 200
else:
gvars.maxblocks = 1000
# check if we are trying nonfbs and not UG
if not gvars.setup_vars.get("fixedBlockSize") and (grid != 'UG' and grid != 'Chombo'):
gvars.out.put("Non-Fixed Block size works only with UG", setup_globals.ERROR)
raise SetupError("Change your grid or switch to fixed block size")
def write_setup_units_file(self):
file = open(os.path.join(gvars.project_setup_dir, setup_globals.SETUP_UNITS_FILENAME), 'w')
file.write("\n".join(self.get_list()))
file.write("\n")
file.close()
def generate_setup_flash_units(self):
fname = os.path.join(gvars.project_setup_dir, setup_globals.SETUP_FLASH_UNITS_FILENAME)
tname = os.path.join(gvars.binDir, setup_globals.SETUP_FLASH_UNITS_TEMPLATE)
tpl = Template(tname)
tpl["unit_names"] = self.get_list()
if len(tpl["unit_names"]) > 39:
p_units = self.parent_units()
c_units = [x for x in self.units.keys() if x not in p_units]
if len(c_units) <= 39:
# if compression actually got us into the allowed range...
c_units.sort()
gvars.out.put("Making list of units for %s more concise by removing parent units:\n reduced %d -> %d unit names.".format(fname, len(tpl["unit_names"]), len(c_units)), setup_globals.INFO)
tpl["unit_names"] = c_units
else:
# exactly one Capitalized component after zero or more small components?
weedable = re.compile("^([a-z][^/]*/)*([A-Z][^/]*)$")
alwayskeep = re.compile("Main$") # never weed out a final *Main component
c_units = [x for x in c_units if not weedable.match(x) or alwayskeep.match(x)]
if len(c_units) <= 39:
# if more compression now got us into the allowed range...
c_units.sort()
gvars.out.put("Making list of units for %s more concise by removing parent and stub-only units:\n reduced %d -> %d unit names.".format(fname, len(tpl["unit_names"]), len(c_units)), setup_globals.INFO)
tpl["unit_names"] = c_units
else:
# exactly one Capitalized component after zero or more
# small components floowed by "/localAPI"?
weedable = re.compile("^([a-z][^/]*/)*([A-Z][^/]*)/localAPI$")
# never weed out a final *Main component
alwayskeep = re.compile("Main/localAPI$")
c_units = [x for x in c_units if not weedable.match(x) or alwayskeep.match(x)]
if len(c_units) <= 39:
# if more compression now got us into the allowed range...
c_units.sort()
gvars.out.put("Making list of units for %s more concise by removing localAPI directories:\n reduced %d -> %d unit names.".format(fname, len(tpl["unit_names"]), len(c_units)), setup_globals.INFO)
tpl["unit_names"] = c_units
tpl.generate(fname)
[docs] def create_makefiles(self):
""" Makefiles: one for each toplevel Unit. Makefiles for subunits get
appended to the top one."""
tname = os.path.join(gvars.binDir, setup_globals.MAKEFILE_STUB_TEMPLATE)
tpl = Template(tname)
for unitname in self.get_list():
lowest_base = get_lowest_base(unitname)
# if we find a unit (ie leaf is a capital
# otherwise it's just an organizational directory
# the exception is "flashUtilities" which is not a
# Unit. Look for it specifically
if not lowest_base[0].isupper():
if lowest_base.find("flashUtilities") >= 0:
lowest_base = "flashUtilities"
else:
continue
source = os.path.join(self.units[unitname].unitpath, "Makefile")
target = 'Makefile.' + lowest_base
target = os.path.join(gvars.project_setup_dir, target)
if os.path.isfile(source):
file = open(target, 'a')
file.write(open(source).read())
file.close()
elif unitname == lowest_base:
tpl["unitname"] = unitname
tpl.generate(target)
#
# Internally called code
#
[docs]def get_lowest_base(base):
"""Return the part of name closest to ROOT dir, which starts with capital letter."""
parts = os.path.normpath(base).split(os.sep)
#import pdb; pdb.set_trace()
x = [p for p in parts if p[0].isupper()]
try:
return x[0]
except IndexError:
return base