Skip to content

Commit 52d90b1

Browse files
committed
Move v1 process output resolution to TaskOutputResolverV1
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
1 parent cac3802 commit 52d90b1

2 files changed

Lines changed: 6 additions & 212 deletions

File tree

modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy

Lines changed: 6 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ import nextflow.script.ScriptMeta
7777
import nextflow.script.ScriptType
7878
import nextflow.script.bundle.ResourcesBundle
7979
import nextflow.script.dsl.Types
80-
import nextflow.script.params.BaseOutParam
81-
import nextflow.script.params.CmdEvalParam
8280
import nextflow.script.params.DefaultOutParam
8381
import nextflow.script.params.EachInParam
8482
import nextflow.script.params.EnvInParam
@@ -1421,7 +1419,7 @@ class TaskProcessor {
14211419
if( config instanceof ProcessConfigV2 )
14221420
collectOutputsV2( task )
14231421
else if( config instanceof ProcessConfigV1 )
1424-
collectOutputsV1( task, task.getTargetDir() )
1422+
collectOutputsV1( task )
14251423
}
14261424

14271425
@CompileStatic
@@ -1442,138 +1440,19 @@ class TaskProcessor {
14421440
task.canBind = true
14431441
}
14441442

1445-
final protected void collectOutputsV1( TaskRun task, Path workDir ) {
1443+
@CompileStatic
1444+
protected void collectOutputsV1( TaskRun task ) {
14461445
log.trace "<$name> collecting output: ${task.outputs}"
14471446

1448-
for( OutParam param : task.outputs.keySet() ) {
1449-
1450-
switch( param ) {
1451-
case StdOutParam:
1452-
collectStdOut(task, (StdOutParam)param, task.@stdout)
1453-
break
1454-
1455-
case FileOutParam:
1456-
collectOutFiles(task, (FileOutParam)param, workDir)
1457-
break
1458-
1459-
case ValueOutParam:
1460-
collectOutValues(task, (ValueOutParam)param, task.context)
1461-
break
1462-
1463-
case EnvOutParam:
1464-
collectOutEnvParam(task, (EnvOutParam)param, workDir)
1465-
break
1447+
final resolver = new TaskOutputResolverV1(task)
14661448

1467-
case CmdEvalParam:
1468-
collectOutEnvParam(task, (CmdEvalParam)param, workDir)
1469-
break
1470-
1471-
case DefaultOutParam:
1472-
task.setOutput(param, DefaultOutParam.Completion.DONE)
1473-
break
1474-
1475-
default:
1476-
throw new IllegalArgumentException("Illegal output parameter: ${param.class.simpleName}")
1477-
1478-
}
1479-
}
1449+
for( OutParam param : task.outputs.keySet() )
1450+
resolver.resolve(param)
14801451

14811452
// mark ready for output binding
14821453
task.canBind = true
14831454
}
14841455

1485-
protected void collectOutEnvParam(TaskRun task, BaseOutParam param, Path workDir) {
1486-
1487-
// fetch the output value
1488-
final outCmds = param instanceof CmdEvalParam ? task.getOutputEvals() : null
1489-
final val = collectOutEnvMap(workDir,outCmds).get(param.name)
1490-
if( val == null && !param.optional )
1491-
throw new MissingValueException("Missing environment variable: $param.name")
1492-
// set into the output set
1493-
task.setOutput(param,val)
1494-
// trace the result
1495-
log.trace "Collecting param: ${param.name}; value: ${val}"
1496-
1497-
}
1498-
1499-
/**
1500-
* Parse the `.command.env` file which holds the value for `env` and `cmd`
1501-
* output types
1502-
*
1503-
* @param workDir
1504-
* The task work directory that contains the `.command.env` file
1505-
* @param outEvals
1506-
* A {@link Map} instance containing key-value pairs
1507-
* @return
1508-
*/
1509-
@CompileStatic
1510-
@Memoized(maxCacheSize = 10_000)
1511-
protected Map collectOutEnvMap(Path workDir, Map<String,String> outEvals) {
1512-
return new TaskEnvCollector(workDir, outEvals).collect()
1513-
}
1514-
1515-
/**
1516-
* Collects the process 'std output'
1517-
*
1518-
* @param task The executed process instance
1519-
* @param param The declared {@link StdOutParam} object
1520-
* @param stdout The object holding the task produced std out object
1521-
*/
1522-
protected void collectStdOut( TaskRun task, StdOutParam param, def stdout ) {
1523-
1524-
if( stdout == null && task.type == ScriptType.SCRIPTLET ) {
1525-
throw new IllegalArgumentException("Missing 'stdout' for process > ${safeTaskName(task)}")
1526-
}
1527-
1528-
if( stdout instanceof Path && !stdout.exists() ) {
1529-
throw new MissingFileException("Missing 'stdout' file: ${stdout.toUriString()} for process > ${safeTaskName(task)}")
1530-
}
1531-
1532-
task.setOutput(param, stdout)
1533-
}
1534-
1535-
protected void collectOutFiles( TaskRun task, FileOutParam param, Path workDir ) {
1536-
1537-
// type file parameter can contain a multiple files pattern separating them with a special character
1538-
final filePatterns = param.getFilePatterns(task.context, task.workDir)
1539-
final opts = [
1540-
followLinks: param.followLinks,
1541-
glob: param.glob,
1542-
hidden: param.hidden,
1543-
includeInputs: param.includeInputs,
1544-
maxDepth: param.maxDepth,
1545-
optional: param.optional || param.arity?.min == 0,
1546-
type: param.type,
1547-
]
1548-
final allFiles = collectOutFiles0(task, filePatterns, opts)
1549-
1550-
if( !param.isValidArity(allFiles.size()) )
1551-
throw new IllegalArityException("Incorrect number of output files for process `${safeTaskName(task)}` -- expected ${param.arity}, found ${allFiles.size()}")
1552-
1553-
task.setOutput( param, allFiles.size()==1 && param.isSingle() ? allFiles[0] : allFiles )
1554-
1555-
}
1556-
1557-
protected List<Path> collectOutFiles0(TaskRun task, List<String> filePatterns, Map opts) {
1558-
return new TaskFileCollector(filePatterns, opts, task).collect()
1559-
}
1560-
1561-
protected void collectOutValues( TaskRun task, ValueOutParam param, Map ctx ) {
1562-
1563-
try {
1564-
// fetch the output value
1565-
final val = param.resolve(ctx)
1566-
// set into the output set
1567-
task.setOutput(param,val)
1568-
// trace the result
1569-
log.trace "Collecting param: ${param.name}; value: ${val}"
1570-
}
1571-
catch( MissingPropertyException e ) {
1572-
throw new MissingValueException("Missing value declared as output parameter: ${e.property}")
1573-
}
1574-
1575-
}
1576-
15771456
@Memoized
15781457
ResourcesBundle getModuleBundle() {
15791458
final script = this.getOwnerScript()

modules/nextflow/src/test/groovy/nextflow/processor/TaskProcessorTest.groovy

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import nextflow.script.ScriptMeta
3939
import nextflow.script.ScriptType
4040
import nextflow.script.bundle.ResourcesBundle
4141
import nextflow.script.params.FileInParam
42-
import nextflow.script.params.FileOutParam
4342
import nextflow.util.CacheHelper
4443
import nextflow.util.MemoryUnit
4544
import spock.lang.Specification
@@ -538,90 +537,6 @@ class TaskProcessorTest extends Specification {
538537
'f*' | ['/a','/b'] | '3' | 'Incorrect number of input files for process `foo` -- expected 3, found 2'
539538
}
540539

541-
def 'should collect output files' () {
542-
given:
543-
def executor = Mock(Executor)
544-
def session = Mock(Session) {getFilePorter()>>Mock(FilePorter) }
545-
def processor = Spy(new TaskProcessor(session:session, executor:executor))
546-
and:
547-
def context = new TaskContext(holder: new HashMap<String, Object>())
548-
def task = new TaskRun(
549-
name: 'foo',
550-
type: ScriptType.SCRIPTLET,
551-
context: context,
552-
config: new TaskConfig())
553-
and:
554-
def workDir = Path.of('/work')
555-
556-
when:
557-
def param = new FileOutParam(new Binding(), [])
558-
.setPathQualifier(true)
559-
.optional(OPTIONAL)
560-
.bind(FILE_NAME) as FileOutParam
561-
if( ARITY )
562-
param.setArity(ARITY)
563-
and:
564-
processor.collectOutFiles(task, param, workDir)
565-
then:
566-
processor.collectOutFiles0(_,_,_) >> RESULTS
567-
and:
568-
task.getOutputs().get(param) == EXPECTED
569-
570-
where:
571-
FILE_NAME | RESULTS | OPTIONAL | ARITY | EXPECTED
572-
'file.txt' | [Path.of('/work/file.txt')] | false | null | Path.of('/work/file.txt')
573-
'*' | [Path.of('/work/file.txt')] | false | null | Path.of('/work/file.txt')
574-
'*' | [Path.of('/work/A'), Path.of('/work/B')] | false | null | [Path.of('/work/A'), Path.of('/work/B')]
575-
'*' | [] | true | null | []
576-
and:
577-
'file.txt' | [Path.of('/work/file.txt')] | false | '1' | Path.of('/work/file.txt')
578-
'*' | [Path.of('/work/file.txt')] | false | '1' | Path.of('/work/file.txt')
579-
'*' | [Path.of('/work/file.txt')] | false | '1..*' | [Path.of('/work/file.txt')]
580-
'*' | [Path.of('/work/A'), Path.of('/work/B')] | false | '2' | [Path.of('/work/A'), Path.of('/work/B')]
581-
'*' | [Path.of('/work/A'), Path.of('/work/B')] | false | '1..*' | [Path.of('/work/A'), Path.of('/work/B')]
582-
'*' | [] | false | '0..*' | []
583-
}
584-
585-
@Unroll
586-
def 'should report output file arity error' () {
587-
given:
588-
def executor = Mock(Executor)
589-
def session = Mock(Session)
590-
def processor = Spy(new TaskProcessor(session:session, executor:executor))
591-
and:
592-
def context = new TaskContext(holder: new HashMap<String, Object>())
593-
def task = new TaskRun(
594-
name: 'foo',
595-
type: ScriptType.SCRIPTLET,
596-
context: context,
597-
config: new TaskConfig())
598-
and:
599-
def workDir = Path.of('/work')
600-
601-
when:
602-
def param = new FileOutParam(new Binding(), [])
603-
.setPathQualifier(true)
604-
.optional(OPTIONAL)
605-
.bind(FILE_NAME) as FileOutParam
606-
if( ARITY )
607-
param.setArity(ARITY)
608-
and:
609-
processor.collectOutFiles(task, param, workDir)
610-
then:
611-
processor.collectOutFiles0(_,_,_) >> RESULTS
612-
and:
613-
def e = thrown(EXCEPTION)
614-
e.message == ERROR
615-
616-
where:
617-
FILE_NAME | RESULTS | OPTIONAL | ARITY | EXCEPTION | ERROR
618-
'file.txt' | [Path.of('/work/file.txt')] | false | '2' | IllegalArityException | "Incorrect number of output files for process `foo` -- expected 2, found 1"
619-
'*' | [Path.of('/work/file.txt')] | false | '2' | IllegalArityException | "Incorrect number of output files for process `foo` -- expected 2, found 1"
620-
'*' | [Path.of('/work/file.txt')] | false | '2..*' | IllegalArityException | "Incorrect number of output files for process `foo` -- expected 2..*, found 1"
621-
'*' | [] | true | '1..*' | IllegalArityException | "Incorrect number of output files for process `foo` -- expected 1..*, found 0"
622-
623-
}
624-
625540
def 'should submit a task' () {
626541
given:
627542
def exec = Mock(Executor)

0 commit comments

Comments
 (0)