Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/reference/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Feature flags with the `nextflow.preview` prefix can cause pipelines run with ne
: When `true`, enables the use of modules with binary scripts. See {ref}`module-binaries` for more information.

`nextflow.enable.strict`
: :::{deprecated} 26.04.0
:::
: When `true`, executes the pipeline in "strict" mode, which introduces the following rules:

- When reading a params file, Nextflow will fail if a dynamic param value references an undefined variable
Expand Down
4 changes: 4 additions & 0 deletions docs/strict-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export NXF_SYNTAX_PARSER=v2
```
:::

:::{versionchanged} 26.04.0
The strict syntax is enabled by default. You can disable it by setting the environment variable `NXF_SYNTAX_PARSER=v1`.
:::

## Overview

The strict syntax is a subset of DSL2. While DSL2 allows any Groovy syntax, the strict syntax allows only a subset of Groovy syntax for Nextflow scripts and config files. This new specification enables more specific error reporting, ensures more consistent code, and will allow the Nextflow language to evolve independently of Groovy.
Expand Down
2 changes: 1 addition & 1 deletion modules/nextflow/src/main/groovy/nextflow/NF.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class NF {
}

static String getSyntaxParserVersion() {
return SysEnv.get('NXF_SYNTAX_PARSER', 'v1')
return SysEnv.get('NXF_SYNTAX_PARSER', 'v2')
}

static boolean isSyntaxParserV2() {
Expand Down
7 changes: 5 additions & 2 deletions modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,9 @@ class CmdRun extends CmdBase implements HubOptions {
}

static void detectStrictFeature(ConfigMap config, Map sysEnv) {
if( NF.isSyntaxParserV2() )
return
final defStrict = sysEnv.get('NXF_ENABLE_STRICT') ?: false
log
final strictMode = config.navigate('nextflow.enable.strict', defStrict)
if( strictMode ) {
log.debug "Enabling nextflow strict mode"
Expand Down Expand Up @@ -522,8 +523,10 @@ class CmdRun extends CmdBase implements HubOptions {
}

static String detectDslMode(ConfigMap config, String scriptText, Map sysEnv) {
// -- try determine DSL version from config file
if( NF.isSyntaxParserV2() )
return DSL2

// -- try determine DSL version from config file
final dsl = config.navigate('nextflow.enable.dsl') as String

// -- script can still override the DSL version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class ConfigBuilder {

List<String> warnings = new ArrayList<>(10)

Map<String,Object> declaredParams = [:]
Map<String,Object> declaredParams

ConfigBuilder() {
setHomeDir(Const.APP_HOME_DIR)
Expand Down Expand Up @@ -407,6 +407,7 @@ class ConfigBuilder {
checkValidProfile(parser.getDeclaredProfiles())
}

this.declaredParams = parser.getDeclaredParams()
}

// guarantee top scopes
Expand Down Expand Up @@ -438,7 +439,6 @@ class ConfigBuilder {
final config = parse0(parser, entry)
if( NF.getSyntaxParserVersion() == 'v1' )
validate(config, entry)
declaredParams.putAll(parser.getDeclaredParams())
result.merge(config)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package nextflow.config.parser.v2
import java.nio.file.NoSuchFileException
import java.nio.file.Path

import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.transform.Memoized
import groovy.util.logging.Slf4j
Expand All @@ -42,13 +43,15 @@ class ConfigDsl extends Script {

private boolean strict

private boolean stripSecrets

private Path configPath

private Map paramOverrides
private Map cliParams

private List<String> profiles

private Map target = [:]
private Map target = [params: [:]]

private Set<String> declaredProfiles = []

Expand All @@ -66,13 +69,21 @@ class ConfigDsl extends Script {
this.strict = value
}

void setStripSecrets(boolean value) {
this.stripSecrets = value
}

void setConfigPath(Path path) {
this.configPath = path
}

void setParams(Map paramOverrides) {
this.paramOverrides = paramOverrides
target.params = paramOverrides
void setParams(Map params) {
this.cliParams = params
(target.params as Map).putAll(params)
}

void setConfigParams(Map params) {
(target.params as Map).putAll(params)
}

void setProfiles(List<String> profiles) {
Expand Down Expand Up @@ -120,7 +131,7 @@ class ConfigDsl extends Script {
void assign(List<String> names, Object value) {
if( names.size() == 2 && names.first() == 'params' ) {
declareParam(names.last(), value)
if( paramOverrides.containsKey(names.last()) )
if( cliParams.containsKey(names.last()) )
return
}
navigate(names.init()).put(names.last(), value)
Expand Down Expand Up @@ -195,8 +206,10 @@ class ConfigDsl extends Script {
.setIgnoreIncludes(ignoreIncludes)
.setRenderClosureAsString(renderClosureAsString)
.setStrict(strict)
.setStripSecrets(stripSecrets)
.setBinding(binding.getVariables())
.setParams(target.params as Map)
.setParams(cliParams)
.setConfigParams(target.params as Map)
.setProfiles(profiles)
final config = parser.parse(configText, includePath)
declaredProfiles.addAll(parser.getDeclaredProfiles())
Expand All @@ -213,6 +226,7 @@ class ConfigDsl extends Script {
* @param includePath
*/
@Memoized
@CompileDynamic // required to support ProviderPath::getText() over NioExtensions::getText()
protected static String readConfigFile(Path includePath) {
try {
return includePath.getText()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package nextflow.config.parser.v2

import java.nio.file.Path

import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import nextflow.config.ConfigParser
import nextflow.exception.ConfigParseException
Expand All @@ -36,7 +37,9 @@ class ConfigParserV2 implements ConfigParser {

private Map bindingVars = [:]

private Map paramOverrides = [:]
private Map cliParams = [:]

private Map configParams = [:]

private boolean ignoreIncludes = false

Expand All @@ -48,9 +51,9 @@ class ConfigParserV2 implements ConfigParser {

private List<String> appliedProfiles

private Set<String> declaredProfiles
private Set<String> declaredProfiles = []

private Map<String,Object> declaredParams
private Map<String,Object> declaredParams = [:]

private GroovyShell groovyShell

Expand Down Expand Up @@ -79,7 +82,7 @@ class ConfigParserV2 implements ConfigParser {
}

@Override
ConfigParser setStripSecrets(boolean value) {
ConfigParserV2 setStripSecrets(boolean value) {
this.stripSecrets = value
return this
}
Expand All @@ -91,10 +94,15 @@ class ConfigParserV2 implements ConfigParser {
}

@Override
ConfigParserV2 setParams(Map vars) {
// deep clone the map to prevent side-effect
ConfigParserV2 setParams(Map params) {
// deep clone the map to prevent side effects with nested params
// see https://github.com/nextflow-io/nextflow/issues/1923
this.paramOverrides = Bolts.deepClone(vars)
this.cliParams = Bolts.deepClone(params)
return this
}

ConfigParserV2 setConfigParams(Map params) {
this.configParams = params
return this
}

Expand Down Expand Up @@ -127,14 +135,17 @@ class ConfigParserV2 implements ConfigParser {
if( path )
script.setConfigPath(path)
script.setIgnoreIncludes(ignoreIncludes)
script.setParams(paramOverrides)
script.setProfiles(appliedProfiles)
script.setRenderClosureAsString(renderClosureAsString)
script.setStrict(strict)
script.setStripSecrets(stripSecrets)
script.setParams(cliParams)
script.setConfigParams(configParams)
script.setProfiles(appliedProfiles)
script.run()

final target = script.getTarget()
declaredProfiles = script.getDeclaredProfiles()
declaredParams = script.getDeclaredParams()
declaredProfiles.addAll(script.getDeclaredProfiles())
declaredParams.putAll(script.getDeclaredParams())
return Bolts.toConfigObject(target)
}
catch( CompilationFailedException e ) {
Expand Down Expand Up @@ -168,8 +179,9 @@ class ConfigParserV2 implements ConfigParser {
}

@Override
@CompileDynamic // required to support ProviderPath::getText() over NioExtensions::getText()
ConfigObject parse(Path path) {
return parse(path.text, path)
return parse(path.getText(), path)
}

private ConfigCompiler compiler
Expand Down
20 changes: 20 additions & 0 deletions modules/nextflow/src/main/groovy/nextflow/scm/ProviderPath.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.nio.file.LinkOption
import java.nio.file.Path
import java.nio.file.Paths

import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.Memoized
import groovy.transform.PackageScope
Expand All @@ -39,6 +40,7 @@ import groovy.util.logging.Slf4j
*/
@EqualsAndHashCode
@Slf4j
@CompileStatic
class ProviderPath implements Path {

@PackageScope
Expand All @@ -59,18 +61,27 @@ class ProviderPath implements Path {
this.delegate = path
}

@Override
Path relativize(Path other) {
new ProviderPath(provider, delegate.relativize(other))
}

@Override
Path resolveSibling(Path other) {
new ProviderPath(provider, delegate.resolveSibling(other.toString()))
}

@Override
Path resolveSibling(String other) {
new ProviderPath(provider, delegate.resolveSibling(other))
}

@Override
Path resolve(Path other) {
new ProviderPath(provider, delegate.resolve(other.toString()))
}

@Override
Path resolve(String other) {
new ProviderPath(provider, delegate.resolve(other))
}
Expand All @@ -97,10 +108,16 @@ class ProviderPath implements Path {
provider.readText(delegate.toString())
}

@Override
URI toUri() {
URI.create(toUriString())
}

String toUriString() {
provider.getContentUrl(delegate.toString())
}

@Override
String toString() {
final base = provider.getRepositoryUrl()
final file = delegate.toString()
Expand All @@ -110,20 +127,23 @@ class ProviderPath implements Path {
/**
* @return the path itself because it's absolute by definition being a remote file
*/
@Override
Path toAbsolutePath() {
return this
}

/**
* @return {@code true} because it's absolute by definition being a remote file
*/
@Override
boolean isAbsolute() {
return true
}

/**
* @return the path itself because it's absolute by definition being a remote file
*/
@Override
Path normalize() {
return this
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,12 @@ abstract class BaseScript extends Script implements ExecutionContext {

private Session session

private ProcessFactory processFactory

private ScriptMeta meta

private WorkflowDef entryFlow

private OutputDef publisher

@Lazy InputStream stdin = { System.in }()

BaseScript() {
meta = ScriptMeta.register(this)
}
Expand Down Expand Up @@ -90,7 +86,6 @@ abstract class BaseScript extends Script implements ExecutionContext {
private void setup() {
binding.owner = this
session = binding.getSession()
processFactory = session.newProcessFactory(this)

binding.setVariable( 'baseDir', session.baseDir )
binding.setVariable( 'projectDir', session.baseDir )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ class BaseScriptConsts {

public static Object[] EMPTY_ARGS = [] as Object[]

public static List<String> PRIVATE_NAMES = ['session','processFactory','taskProcessor','meta','entryFlow', 'publisher']
public static List<String> PRIVATE_NAMES = ['session','meta','entryFlow', 'publisher']
}
Loading
Loading