def generateParametricJobs( jobClassAd ): """ Generate a series of ClassAd job descriptions expanding job parameters :param jobClassAd: ClassAd job description object :return: list of ClassAd job description objects """ if not jobClassAd.lookupAttribute( 'Parameters' ): return S_OK( [ jobClassAd.asJDL() ] ) result = getParameterVectorLength( jobClassAd ) if not result['OK']: return result nParValues = result['Value'] if nParValues is None: return S_ERROR(EWMSJDL, 'Can not determine the number of job parameters') parameterDict = {} attributes = jobClassAd.getAttributes() for attribute in attributes: for key in [ 'Parameters', 'ParameterStart', 'ParameterStep', 'ParameterFactor' ]: if attribute.startswith( key ): seqID = '0' if not '.' in attribute else attribute.split( '.' )[1] parameterDict.setdefault( seqID, {} ) if key == 'Parameters': if jobClassAd.isAttributeList( attribute ): parList = jobClassAd.getListFromExpression( attribute ) if len( parList ) != nParValues: return S_ERROR( EWMSJDL, 'Inconsistent parametric job description' ) parameterDict[seqID]['ParameterList'] = parList else: if attribute != "Parameters": return S_ERROR( EWMSJDL, 'Inconsistent parametric job description' ) nPar = jobClassAd.getAttributeInt( attribute ) if nPar is None: value = jobClassAd.get_expression( attribute ) return S_ERROR( EWMSJDL, 'Inconsistent parametric job description: %s=%s' % ( attribute, value ) ) parameterDict[seqID]['Parameters'] = nPar else: value = jobClassAd.getAttributeInt( attribute ) if value is None: value = jobClassAd.getAttributeFloat( attribute ) if value is None: value = jobClassAd.get_expression( attribute ) return S_ERROR( 'Illegal value for %s JDL field: %s' % ( attribute, value ) ) parameterDict[seqID][key] = value if '0' in parameterDict and not parameterDict.get( '0' ): parameterDict.pop( '0' ) parameterLists = {} for seqID in parameterDict: parList = __getParameterSequence( nParValues, parList = parameterDict[seqID].get( 'ParameterList', [] ), parStart = parameterDict[seqID].get( 'ParameterStart', 1 ), parStep = parameterDict[seqID].get( 'ParameterStep', 0 ), parFactor = parameterDict[seqID].get( 'ParameterFactor', 1 ) ) if not parList: return S_ERROR( EWMSJDL, 'Inconsistent parametric job description' ) parameterLists[seqID] = parList jobDescList = [] jobDesc = jobClassAd.asJDL() # Width of the sequential parameter number zLength = len( str( nParValues - 1 ) ) for n in range( nParValues ): newJobDesc = jobDesc newJobDesc = newJobDesc.replace( '%n', str( n ).zfill( zLength ) ) newClassAd = ClassAd( newJobDesc ) for seqID in parameterLists: parameter = parameterLists[seqID][n] for attribute in newClassAd.getAttributes(): __updateAttribute( newClassAd, attribute, seqID, str( parameter ) ) for seqID in parameterLists: for attribute in ['Parameters', 'ParameterStart', 'ParameterStep', 'ParameterFactor']: if seqID == '0': newClassAd.deleteAttribute( attribute ) else: newClassAd.deleteAttribute( '%s.%s' % ( attribute, seqID ) ) parameter = parameterLists[seqID][n] if seqID == '0': attribute = 'Parameter' else: attribute = 'Parameter.%s' % seqID if isinstance( parameter, basestring) and parameter.startswith( '{' ): newClassAd.insertAttributeInt( attribute, str( parameter ) ) else: newClassAd.insertAttributeString( attribute, str( parameter ) ) newClassAd.insertAttributeInt( 'ParameterNumber', n ) newJDL = newClassAd.asJDL() jobDescList.append( newJDL ) return S_OK( jobDescList )
def generateParametricJobs(jobClassAd): """ Generate a series of ClassAd job descriptions expanding job parameters :param jobClassAd: ClassAd job description object :return: list of ClassAd job description objects """ if not jobClassAd.lookupAttribute('Parameters'): return S_OK([jobClassAd.asJDL()]) result = getParameterVectorLength(jobClassAd) if not result['OK']: return result nParValues = result['Value'] if nParValues is None: return S_ERROR(EWMSJDL, 'Can not determine the number of job parameters') parameterDict = {} attributes = jobClassAd.getAttributes() for attribute in attributes: for key in [ 'Parameters', 'ParameterStart', 'ParameterStep', 'ParameterFactor' ]: if attribute.startswith(key): seqID = '0' if '.' not in attribute else attribute.split( '.')[1] parameterDict.setdefault(seqID, {}) if key == 'Parameters': if jobClassAd.isAttributeList(attribute): parList = jobClassAd.getListFromExpression(attribute) if len(parList) != nParValues: return S_ERROR( EWMSJDL, 'Inconsistent parametric job description') parameterDict[seqID]['ParameterList'] = parList else: if attribute != "Parameters": return S_ERROR( EWMSJDL, 'Inconsistent parametric job description') nPar = jobClassAd.getAttributeInt(attribute) if nPar is None: value = jobClassAd.get_expression(attribute) return S_ERROR( EWMSJDL, 'Inconsistent parametric job description: %s=%s' % (attribute, value)) parameterDict[seqID]['Parameters'] = nPar else: value = jobClassAd.getAttributeInt(attribute) if value is None: value = jobClassAd.getAttributeFloat(attribute) if value is None: value = jobClassAd.get_expression(attribute) return S_ERROR( 'Illegal value for %s JDL field: %s' % (attribute, value)) parameterDict[seqID][key] = value if '0' in parameterDict and not parameterDict.get('0'): parameterDict.pop('0') parameterLists = {} for seqID in parameterDict: parList = __getParameterSequence( nParValues, parList=parameterDict[seqID].get('ParameterList', []), parStart=parameterDict[seqID].get('ParameterStart', 1), parStep=parameterDict[seqID].get('ParameterStep', 0), parFactor=parameterDict[seqID].get('ParameterFactor', 1)) if not parList: return S_ERROR(EWMSJDL, 'Inconsistent parametric job description') parameterLists[seqID] = parList jobDescList = [] jobDesc = jobClassAd.asJDL() # Width of the sequential parameter number zLength = len(str(nParValues - 1)) for n in range(nParValues): newJobDesc = jobDesc newJobDesc = newJobDesc.replace('%n', str(n).zfill(zLength)) newClassAd = ClassAd(newJobDesc) for seqID in parameterLists: parameter = parameterLists[seqID][n] for attribute in newClassAd.getAttributes(): __updateAttribute(newClassAd, attribute, seqID, str(parameter)) for seqID in parameterLists: for attribute in [ 'Parameters', 'ParameterStart', 'ParameterStep', 'ParameterFactor' ]: if seqID == '0': newClassAd.deleteAttribute(attribute) else: newClassAd.deleteAttribute('%s.%s' % (attribute, seqID)) parameter = parameterLists[seqID][n] if seqID == '0': attribute = 'Parameter' else: attribute = 'Parameter.%s' % seqID if isinstance(parameter, six.string_types) and parameter.startswith('{'): newClassAd.insertAttributeInt(attribute, str(parameter)) else: newClassAd.insertAttributeString(attribute, str(parameter)) newClassAd.insertAttributeInt('ParameterNumber', n) newJDL = newClassAd.asJDL() jobDescList.append(newJDL) return S_OK(jobDescList)
def generateParametricJobs(jobClassAd): """Generate a series of ClassAd job descriptions expanding job parameters :param jobClassAd: ClassAd job description object :return: list of ClassAd job description objects """ if not jobClassAd.lookupAttribute("Parameters"): return S_OK([jobClassAd.asJDL()]) result = getParameterVectorLength(jobClassAd) if not result["OK"]: return result nParValues = result["Value"] if nParValues is None: return S_ERROR(EWMSJDL, "Can not determine the number of job parameters") parameterDict = {} attributes = jobClassAd.getAttributes() for attribute in attributes: for key in [ "Parameters", "ParameterStart", "ParameterStep", "ParameterFactor" ]: if attribute.startswith(key): seqID = "0" if "." not in attribute else attribute.split( ".")[1] parameterDict.setdefault(seqID, {}) if key == "Parameters": if jobClassAd.isAttributeList(attribute): parList = jobClassAd.getListFromExpression(attribute) if len(parList) != nParValues: return S_ERROR( EWMSJDL, "Inconsistent parametric job description") parameterDict[seqID]["ParameterList"] = parList else: if attribute != "Parameters": return S_ERROR( EWMSJDL, "Inconsistent parametric job description") nPar = jobClassAd.getAttributeInt(attribute) if nPar is None: value = jobClassAd.get_expression(attribute) return S_ERROR( EWMSJDL, "Inconsistent parametric job description: %s=%s" % (attribute, value)) parameterDict[seqID]["Parameters"] = nPar else: value = jobClassAd.getAttributeInt(attribute) if value is None: value = jobClassAd.getAttributeFloat(attribute) if value is None: value = jobClassAd.get_expression(attribute) return S_ERROR( "Illegal value for %s JDL field: %s" % (attribute, value)) parameterDict[seqID][key] = value if "0" in parameterDict and not parameterDict.get("0"): parameterDict.pop("0") parameterLists = {} for seqID in parameterDict: parList = __getParameterSequence( nParValues, parList=parameterDict[seqID].get("ParameterList", []), parStart=parameterDict[seqID].get("ParameterStart", 1), parStep=parameterDict[seqID].get("ParameterStep", 0), parFactor=parameterDict[seqID].get("ParameterFactor", 1), ) if not parList: return S_ERROR(EWMSJDL, "Inconsistent parametric job description") parameterLists[seqID] = parList jobDescList = [] jobDesc = jobClassAd.asJDL() # Width of the sequential parameter number zLength = len(str(nParValues - 1)) for n in range(nParValues): newJobDesc = jobDesc newJobDesc = newJobDesc.replace("%n", str(n).zfill(zLength)) newClassAd = ClassAd(newJobDesc) for seqID in parameterLists: parameter = parameterLists[seqID][n] for attribute in newClassAd.getAttributes(): __updateAttribute(newClassAd, attribute, seqID, str(parameter)) for seqID in parameterLists: for attribute in [ "Parameters", "ParameterStart", "ParameterStep", "ParameterFactor" ]: if seqID == "0": newClassAd.deleteAttribute(attribute) else: newClassAd.deleteAttribute("%s.%s" % (attribute, seqID)) parameter = parameterLists[seqID][n] if seqID == "0": attribute = "Parameter" else: attribute = "Parameter.%s" % seqID if isinstance(parameter, str) and parameter.startswith("{"): newClassAd.insertAttributeInt(attribute, str(parameter)) else: newClassAd.insertAttributeString(attribute, str(parameter)) newClassAd.insertAttributeInt("ParameterNumber", n) newJDL = newClassAd.asJDL() jobDescList.append(newJDL) return S_OK(jobDescList)