Skip to content

Commit db9d727

Browse files
committed
Workflow params (part 1)
Signed-off-by: Ben Sherman <[email protected]>
1 parent cdb13af commit db9d727

38 files changed

+813
-239
lines changed

docs/cli.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ Parameters are applied in the following order (from lowest to highest priority):
297297

298298
1. Parameters defined in pipeline scripts (e.g. `main.nf`)
299299
2. Parameters defined in {ref}`config files <config-params>`
300-
6. Parameters specified in a params file (`-params-file`)
301-
7. Parameters specified on the command line (`--something value`)
300+
3. Parameters specified in a params file (`-params-file`)
301+
4. Parameters specified on the command line (`--something value`)
302302

303303
## Managing projects
304304

docs/reference/syntax.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ A Nextflow script may contain the following top-level declarations:
2828
- Shebang
2929
- Feature flags
3030
- Include declarations
31-
- Parameter declarations
31+
- Params block
32+
- Parameter declarations (legacy)
3233
- Workflow definitions
3334
- Process definitions
3435
- Function definitions
@@ -107,9 +108,22 @@ The following definitions can be included:
107108
- Processes
108109
- Named workflows
109110

110-
### Parameter
111+
### Params block
111112

112-
A parameter declaration is an assignment. The target should be a pipeline parameter and the source should be an expression:
113+
The params block consists of one or more *parameter declarations*. A parameter declaration consists of a name and an optional default value:
114+
115+
```nextflow
116+
params {
117+
input
118+
save_intermeds = false
119+
}
120+
```
121+
122+
Only one params block may be defined in a script.
123+
124+
### Parameter (legacy)
125+
126+
A legacy parameter declaration is an assignment. The target should be a pipeline parameter and the source should be an expression:
113127

114128
```nextflow
115129
params.message = 'Hello world!'

docs/vscode.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ The language server parses scripts and config files according to the {ref}`Nextf
2626

2727
When you hover over certain source code elements, such as variable names and function calls, the extension provides a tooltip with related information, such as the definition and/or documentation for the element.
2828

29+
If a [Javadoc](https://en.wikipedia.org/wiki/Javadoc) comment is defined above a workflow, process, function, type definition, or parameter in a `params` block, the extension will include the contents of the comment in hover hints. The following is an example Javadoc comment:
30+
31+
```nextflow
32+
/**
33+
* Say hello to someone.
34+
*
35+
* @param name
36+
*/
37+
def sayHello(name) {
38+
println "Hello, ${name}!"
39+
}
40+
```
41+
2942
### Code navigation
3043

3144
The **Outline** section in the Explorer panel lists top-level definitions when you view a script. Include declarations in scripts and config files act as links, and ctrl-clicking them opens the corresponding script or config file.

docs/workflow.md

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,67 @@ workflow {
2222
}
2323
```
2424

25-
### Parameters
25+
## Parameters
2626

27-
Parameters can be defined in the script with a default value that can be overridden from the CLI, params file, or config file. Parameters should only be used by the entry workflow:
27+
Parameters can be declared in a Nextflow script with the `params` block or with *legacy* parameter declarations.
28+
29+
### Params block
30+
31+
:::{versionadded} 25.05.0-edge
32+
:::
33+
34+
:::{note}
35+
This feature requires the {ref}`strict syntax <strict-syntax-page>` to be enabled (`NXF_SYNTAX_PARSER=v2`).
36+
:::
37+
38+
A script can declare parameters using the `params` block:
39+
40+
```nextflow
41+
params {
42+
/**
43+
* Path to input data.
44+
*/
45+
input
46+
47+
/**
48+
* Whether to save intermediate files.
49+
*/
50+
save_intermeds = false
51+
}
52+
```
53+
54+
Parameters can be used in the entry workflow:
55+
56+
```nextflow
57+
workflow {
58+
if( params.input )
59+
analyze(params.input, params.save_intermeds)
60+
else
61+
analyze(fake_input(), params.save_intermeds)
62+
}
63+
```
64+
65+
:::{note}
66+
While params can be used outside the entry workflow, Nextflow will not be able to validate them at compile-time. Only params used in the entry workflow are validated against the params definition. Params can be passed to workflows and processes as explicit inputs to enable compile-time validation.
67+
:::
68+
69+
The default value can be overridden by the command line, params file, or config file. Parameters from multiple sources are resolved in the order described in {ref}`cli-params`.
70+
71+
A parameter that doesn't specify a default value is a *required* param. If a required param is not given a value at runtime, the run will fail.
72+
73+
### Legacy parameters
74+
75+
Parameters can be declared by assigning a `params` property to a default value:
2876

2977
```nextflow
30-
params.data = '/some/data/file'
78+
params.input = '/some/data/file'
79+
params.save_intermeds = false
3180
3281
workflow {
33-
if( params.data )
34-
bar(params.data)
82+
if( params.input )
83+
analyze(params.input, params.save_intermeds)
3584
else
36-
bar(foo())
85+
analyze(fake_input(), params.save_intermeds)
3786
}
3887
```
3988

modules/nextflow/src/main/groovy/nextflow/Session.groovy

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ class Session implements ISession {
113113
*/
114114
ScriptBinding binding
115115

116+
/**
117+
* Params that were specified on the command line.
118+
*/
119+
Map cliParams
120+
121+
/**
122+
* Params that were specified in the configuration.
123+
*/
124+
Map configParams
125+
116126
/**
117127
* Holds the configuration object
118128
*/
@@ -418,7 +428,7 @@ class Session implements ISession {
418428
/**
419429
* Initialize the session workDir, libDir, baseDir and scriptName variables
420430
*/
421-
Session init( ScriptFile scriptFile, List<String> args=null ) {
431+
Session init( ScriptFile scriptFile, List<String> args=null, Map<String,?> cliParams=null, Map<String,?> configParams=null ) {
422432

423433
if(!workDir.mkdirs()) throw new AbortOperationException("Cannot create work-dir: $workDir -- Make sure you have write permissions or specify a different directory by using the `-w` command line option")
424434
log.debug "Work-dir: ${workDir.toUriString()} [${FileHelper.getPathFsType(workDir)}]"
@@ -445,6 +455,8 @@ class Session implements ISession {
445455
this.workflowMetadata = new WorkflowMetadata(this, scriptFile)
446456

447457
// configure script params
458+
this.cliParams = cliParams
459+
this.configParams = configParams
448460
binding.setParams( (Map)config.params )
449461
binding.setArgs( new ScriptRunner.ArgsList(args) )
450462

modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,12 +325,18 @@ class CmdRun extends CmdBase implements HubOptions {
325325
// -- specify the arguments
326326
final scriptFile = getScriptFile(pipeline)
327327

328+
// -- load command line params
329+
final baseDir = scriptFile.parent
330+
final cliParams = parsedParams(ConfigBuilder.getConfigVars(baseDir))
331+
328332
// create the config object
329333
final builder = new ConfigBuilder()
330334
.setOptions(launcher.options)
331335
.setCmdRun(this)
332-
.setBaseDir(scriptFile.parent)
333-
final config = builder .build()
336+
.setBaseDir(baseDir)
337+
.setCliParams(cliParams)
338+
final config = builder.build()
339+
final configParams = builder.getConfigParams()
334340

335341
// check DSL syntax in the config
336342
launchInfo(config, scriptFile)
@@ -376,7 +382,7 @@ class CmdRun extends CmdBase implements HubOptions {
376382
}
377383

378384
// -- run it!
379-
runner.execute(scriptArgs, this.entryName)
385+
runner.execute(scriptArgs, cliParams, configParams, this.entryName)
380386
}
381387

382388
protected void printBanner() {

modules/nextflow/src/main/groovy/nextflow/config/ConfigBuilder.groovy

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class ConfigBuilder {
6161

6262
Path currentDir
6363

64+
Map<String,?> cliParams
65+
6466
boolean showAllProfiles
6567

6668
String profile = DEFAULT_PROFILE
@@ -81,9 +83,11 @@ class ConfigBuilder {
8183

8284
Map<String,String> env = new HashMap<>(System.getenv())
8385

84-
List<String> warnings = new ArrayList<>(10);
86+
List<String> warnings = new ArrayList<>(10)
87+
88+
Map<String,Object> declaredParams = [:]
8589

86-
{
90+
ConfigBuilder() {
8791
setHomeDir(Const.APP_HOME_DIR)
8892
setCurrentDir(Paths.get('.'))
8993
}
@@ -114,6 +118,11 @@ class ConfigBuilder {
114118
return this
115119
}
116120

121+
ConfigBuilder setCliParams( Map<String,?> cliParams ) {
122+
this.cliParams = cliParams
123+
return this
124+
}
125+
117126
ConfigBuilder setBaseDir( Path path ) {
118127
this.baseDir = path.complete()
119128
return this
@@ -162,6 +171,10 @@ class ConfigBuilder {
162171
return this
163172
}
164173

174+
Map<String,Object> getConfigParams() {
175+
return declaredParams
176+
}
177+
165178
static private wrapValue( value ) {
166179
if( !value )
167180
return ''
@@ -327,11 +340,11 @@ class ConfigBuilder {
327340
// this is needed to make sure to reuse the same
328341
// instance of the config vars across different instances of the ConfigBuilder
329342
// and prevent multiple parsing of the same params file (which can even be remote resource)
330-
return cacheableConfigVars(baseDir)
343+
return getConfigVars(baseDir)
331344
}
332345

333346
@Memoized
334-
static private Map cacheableConfigVars(Path base) {
347+
static Map getConfigVars(Path base) {
335348
final binding = new HashMap(10)
336349
binding.put('baseDir', base)
337350
binding.put('projectDir', base)
@@ -351,8 +364,8 @@ class ConfigBuilder {
351364
.setIgnoreIncludes(ignoreIncludes)
352365
ConfigObject result = new ConfigObject()
353366

354-
if( cmdRun && (cmdRun.hasParams()) )
355-
parser.setParams(cmdRun.parsedParams(configVars()))
367+
if( cliParams )
368+
parser.setParams(cliParams)
356369

357370
// add the user specified environment to the session env
358371
env.sort().each { name, value -> result.env.put(name,value) }
@@ -383,7 +396,7 @@ class ConfigBuilder {
383396
}
384397

385398
if( validateProfile ) {
386-
checkValidProfile(parser.getProfiles())
399+
checkValidProfile(parser.getDeclaredProfiles())
387400
}
388401

389402
}
@@ -414,9 +427,10 @@ class ConfigBuilder {
414427
parser.setProfiles(profile.tokenize(','))
415428
}
416429

417-
final config = parse0(parser, entry)
430+
def config = parse0(parser, entry)
418431
if( NF.getSyntaxParserVersion() == 'v1' )
419432
validate(config, entry)
433+
declaredParams.putAll(parser.getDeclaredParams())
420434
result.merge(config)
421435
}
422436

@@ -734,8 +748,8 @@ class ConfigBuilder {
734748
}
735749

736750
// -- add the command line parameters to the 'taskConfig' object
737-
if( cmdRun.hasParams() )
738-
config.params = mergeMaps( (Map)config.params, cmdRun.parsedParams(configVars()), NF.strictMode )
751+
if( cliParams )
752+
config.params = mergeMaps( (Map)config.params, cliParams, NF.strictMode )
739753

740754
if( cmdRun.withoutDocker && config.docker instanceof Map ) {
741755
// disable docker execution

modules/nextflow/src/main/groovy/nextflow/config/ConfigParser.groovy

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ interface ConfigParser {
6767
*/
6868
ConfigParser setParams(Map vars)
6969

70+
/**
71+
* Set the profiles that should be applied.
72+
*/
73+
ConfigParser setProfiles(List<String> profiles)
74+
7075
/**
7176
* Parse a config object from the given source.
7277
*/
@@ -75,13 +80,13 @@ interface ConfigParser {
7580
ConfigObject parse(Path path)
7681

7782
/**
78-
* Set the profiles that should be applied.
83+
* Get the set of declared profiles.
7984
*/
80-
ConfigParser setProfiles(List<String> profiles)
85+
Set<String> getDeclaredProfiles()
8186

8287
/**
83-
* Get the set of available profiles.
88+
* Get the map of declared params.
8489
*/
85-
Set<String> getProfiles()
90+
Map<String,Object> getDeclaredParams()
8691

8792
}

modules/nextflow/src/main/groovy/nextflow/config/parser/v1/ConfigParserV1.groovy

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,15 @@ class ConfigParserV1 implements ConfigParser {
123123
}
124124

125125
@Override
126-
Set<String> getProfiles() {
126+
Set<String> getDeclaredProfiles() {
127127
Collections.unmodifiableSet(conditionalNames)
128128
}
129129

130+
@Override
131+
Map<String,Object> getDeclaredParams() {
132+
[:]
133+
}
134+
130135
private Grengine getGrengine() {
131136
if( grengine ) {
132137
return grengine

0 commit comments

Comments
 (0)