Skip to content

Commit

Permalink
[#1571] interpolate variables in values from default value provider
Browse files Browse the repository at this point in the history
Closes #1571
  • Loading branch information
remkop committed Feb 11, 2022
1 parent 549affa commit 20468f4
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 11 deletions.
4 changes: 2 additions & 2 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The picocli community is pleased to announce picocli 4.7.0.
This release includes bugfixes and enhancements.


This is the seventy-nineth public release.
This is the seventy-ninth public release.
Picocli follows [semantic versioning](http://semver.org/).
Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).

Expand All @@ -23,7 +23,7 @@ Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
* [#1396][#1401] API: Support generic types in containers (e.g. List, Map). Thanks to [Michał Górniewski](https://github.com/mgorniew) for the pull request.
* [#1380][#1505] API, bugfix: `requiredOptionMarker` should not be displayed on `ArgGroup` options. Thanks to [Ahmed El Khalifa](https://github.com/ahmede41) for the pull request.
* [#1563] API: Add constructor to `PicocliSpringFactory` to allow custom fallback `IFactory`. Thanks to [Andrew Holland](https://github.com/a1dutch) for raising this.

* [#1571] Enhancement: Variables in values from the default value provider should be interpolated. Thanks to [Bas Passon](https://github.com/bpasson) for raising this.


## <a name="4.7.0-deprecated"></a> Deprecations
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/picocli/CommandLine.java
Original file line number Diff line number Diff line change
Expand Up @@ -13329,7 +13329,7 @@ private boolean applyDefault(IDefaultValueProvider defaultValueProvider, ArgSpec
// Default value provider return value is only used if provider exists and if value
// is not null otherwise the original default or initial value are used
String fromProvider = defaultValueProvider == null ? null : defaultValueProvider.defaultValue(arg);
String defaultValue = fromProvider == null ? arg.defaultValue() : fromProvider;
String defaultValue = fromProvider == null ? arg.defaultValue() : arg.interpolate(fromProvider);
String provider = defaultValueProvider == null ? "" : (" from " + defaultValueProvider.toString());

if (defaultValue != null && !ArgSpec.NULL_VALUE.equals(defaultValue)) {
Expand Down
108 changes: 100 additions & 8 deletions src/test/java/picocli/DefaultProviderTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package picocli;

import static java.lang.String.format;
import static org.junit.Assert.*;
import static picocli.CommandLine.Option.NULL_VALUE;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.contrib.java.lang.system.ProvideSystemProperty;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.rules.TestRule;
Expand All @@ -16,15 +13,14 @@
import picocli.CommandLine.Parameters;
import picocli.CommandLine.PropertiesDefaultProvider;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListResourceBundle;
import java.util.Properties;

import static org.junit.Assert.*;

public class DefaultProviderTest {

// allows tests to set any kind of properties they like, without having to individually roll them back
Expand All @@ -34,6 +30,9 @@ public class DefaultProviderTest {
@Rule
public final ProvideSystemProperty ansiOFF = new ProvideSystemProperty("picocli.ansi", "false");

@Rule
public final EnvironmentVariables envVars = new EnvironmentVariables();

static class TestDefaultProvider implements IDefaultValueProvider {
public String defaultValue(ArgSpec argSpec) {
return "Default provider string value";
Expand Down Expand Up @@ -363,4 +362,97 @@ class App {
App app1 = CommandLine.populateCommand(new App());
assertEquals(null, app1.a);
}

static class DefaultProviderWithVariables implements IDefaultValueProvider {
static String value = "${VARIABLE:-555}";
public String defaultValue(ArgSpec argSpec) throws Exception {
return value;
}
}

@Test
public void testDefaultValueProviderWithVariablesUsesFallbackIfNoSystemPropEnvVarOrResourceBundle() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class)
class App {
@Option(names = "-a")
int a;
}
App app1 = CommandLine.populateCommand(new App());
assertEquals(555, app1.a);
}

@Test
public void testDefaultValueProviderWithVariablesResolvesSystemProperty() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class)
class App {
@Option(names = "-a")
int a;
}
System.setProperty("VARIABLE", "123");
App app1 = CommandLine.populateCommand(new App());
assertEquals(123, app1.a);
}

@Test
public void testDefaultValueProviderWithVariablesPrefersSystemPropertyOverEnvVars() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class)
class App {
@Option(names = "-a")
int a;
}
System.setProperty("VARIABLE", "123");
envVars.set("VARIABLE", "456");
App app1 = CommandLine.populateCommand(new App());
assertEquals(123, app1.a);
}

@Test
public void testDefaultValueProviderWithVariablesResolvesEnvironmentVariable() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class)
class App {
@Option(names = "-a")
int a;
}
envVars.set("VARIABLE", "456");
App app1 = CommandLine.populateCommand(new App());
assertEquals(456, app1.a);
}

@Test
public void testDefaultValueProviderWithVariablesResolvesResourceBundle() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class,
resourceBundle = "picocli.DefaultProviderTestBundle")
class App {
@Option(names = "-a")
int a;
}
App app1 = CommandLine.populateCommand(new App());
assertEquals(789, app1.a);
}

@Test
public void testDefaultValueProviderWithVariablesPrefersSystemPropertyOverResourceBundle() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class,
resourceBundle = "picocli.DefaultProviderTestBundle")
class App {
@Option(names = "-a")
int a;
}
System.setProperty("VARIABLE", "123");
App app1 = CommandLine.populateCommand(new App());
assertEquals(123, app1.a);
}

@Test
public void testDefaultValueProviderWithVariablesPrefersEnvVarsOverResourceBundle() {
@Command(defaultValueProvider = DefaultProviderWithVariables.class,
resourceBundle = "picocli.DefaultProviderTestBundle")
class App {
@Option(names = "-a")
int a;
}
envVars.set("VARIABLE", "456");
App app1 = CommandLine.populateCommand(new App());
assertEquals(456, app1.a);
}
}
16 changes: 16 additions & 0 deletions src/test/java/picocli/DefaultProviderTestBundle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package picocli;

import java.util.ListResourceBundle;

/**
* Resource bundle for DefaultProviderTest#testDefaultValueProviderWithVariablesResolvesResourceBundle
*/
public class DefaultProviderTestBundle extends ListResourceBundle {
protected Object[][] getContents() {
return new Object[][] {
// KEY VALUE PAIRS
{"VARIABLE", "789"},
// END OF MATERIAL TO LOCALIZE
};
}
}

0 comments on commit 20468f4

Please sign in to comment.