Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4fd28fd

Browse files
authored
Fix module run to allow optional path inputs (#7163)
Signed-off-by: Ben Sherman <[email protected]>
1 parent 0498ca6 commit 4fd28fd

2 files changed

Lines changed: 80 additions & 3 deletions

File tree

modules/nextflow/src/main/groovy/nextflow/script/ProcessEntryHandler.groovy

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ class ProcessEntryHandler {
238238
}
239239

240240
/**
241-
* Load mapping of input types from the module spec if available. Returns null
241+
* Load mapping of input types from the module spec if available. Returns empty map
242242
* if module spec is absent or unreadable.
243243
*/
244244
private static Map<String, Class> getModuleSpecInputTypes(Path scriptPath) {
@@ -294,6 +294,10 @@ class ProcessEntryHandler {
294294
final value = namedArgs.get(name)
295295

296296
if( value == null ) {
297+
if( param instanceof FileInParam ) {
298+
log.warn "Path input '--${name}' not provided, defaulting to empty list"
299+
return []
300+
}
297301
throw new IllegalArgumentException("Missing required parameter: --${name}")
298302
}
299303

@@ -397,6 +401,8 @@ class ProcessEntryHandler {
397401
final value = namedArgs.get(name)
398402

399403
if( value == null ) {
404+
if( param.isOptional() )
405+
return null
400406
throw new IllegalArgumentException("Missing required parameter: --${name}")
401407
}
402408

@@ -433,10 +439,10 @@ class ProcessEntryHandler {
433439
* Otherwise returns a single file object.
434440
*
435441
* @param fileInput String representation of file path(s)
436-
* @return Single file object or List of file objects
442+
* @return Single file or list of files
437443
*/
438444
protected Object parseFileInput(String fileInput) {
439-
if (fileInput.contains(',')) {
445+
if( fileInput.contains(',') ) {
440446
// Split by comma, trim whitespace, and convert each to a file
441447
return fileInput.tokenize(',')
442448
.collect { it.trim() }

modules/nextflow/src/test/groovy/nextflow/script/ProcessEntryHandlerTest.groovy

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,4 +392,75 @@ class ProcessEntryHandlerTest extends Specification {
392392
'/path/to/file1.txt,,/path/to/file2.txt, ,/path/to/file3.txt' | [Path.of('/path/to/file1.txt'), Path.of('/path/to/file2.txt'), Path.of('/path/to/file3.txt')]
393393
'file1.txt,file2.txt' | [Path.of('file1.txt').toAbsolutePath(), Path.of('file2.txt').toAbsolutePath()]
394394
}
395+
396+
def 'should return empty list for missing path input (v1)' () {
397+
given:
398+
def session = Mock(Session)
399+
def script = Mock(BaseScript)
400+
def meta = Mock(ScriptMeta) {
401+
getLocalProcessNames() >> [ 'hello' ]
402+
}
403+
def handler = new ProcessEntryHandler(script, session, meta)
404+
def pathParam = Mock(FileInParam) { getName() >> 'intervals' }
405+
406+
when: 'the input is not present in params for a path input'
407+
def result = handler.getValueForInputV1(pathParam, [:], [:])
408+
409+
then: 'returns an empty list instead of throwing'
410+
result == []
411+
}
412+
413+
def 'should throw error for missing val input (v1)' () {
414+
given:
415+
def session = Mock(Session)
416+
def script = Mock(BaseScript)
417+
def meta = Mock(ScriptMeta) {
418+
getLocalProcessNames() >> [ 'hello' ]
419+
}
420+
def handler = new ProcessEntryHandler(script, session, meta)
421+
def valParam = Mock(ValueInParam) { getName() >> 'id' }
422+
423+
when: 'a val input is absent'
424+
handler.getValueForInputV1(valParam, [:], [:])
425+
426+
then:
427+
def e = thrown(IllegalArgumentException)
428+
e.message == 'Missing required parameter: --id'
429+
}
430+
431+
def 'should return null for missing optional input (v2)' () {
432+
// Regression test for https://github.com/nextflow-io/nextflow/issues/7161
433+
given:
434+
def session = Mock(Session)
435+
def script = Mock(BaseScript)
436+
def meta = Mock(ScriptMeta) {
437+
getLocalProcessNames() >> [ 'hello' ]
438+
}
439+
def handler = new ProcessEntryHandler(script, session, meta)
440+
def param = new ProcessInput('gzi', Path, true)
441+
442+
when: 'a v2 optional path input is not provided'
443+
def result = handler.getValueForInputV2(param, [:])
444+
445+
then: 'returns null instead of throwing'
446+
result == null
447+
}
448+
449+
def 'should throw error for missing required input (v2)' () {
450+
given:
451+
def session = Mock(Session)
452+
def script = Mock(BaseScript)
453+
def meta = Mock(ScriptMeta) {
454+
getLocalProcessNames() >> [ 'hello' ]
455+
}
456+
def handler = new ProcessEntryHandler(script, session, meta)
457+
def param = new ProcessInput('reads', Path, false)
458+
459+
when:
460+
handler.getValueForInputV2(param, [:])
461+
462+
then:
463+
def e = thrown(IllegalArgumentException)
464+
e.message == 'Missing required parameter: --reads'
465+
}
395466
}

0 commit comments

Comments
 (0)