aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Laurent Le Brun <laurentlb@google.com>2015-05-08 15:00:35 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-05-08 17:01:17 +0000
commitaa83c3aaffc4c55b6cb8adec88456903321ceecc (patch)
tree848f706a27fe90a8f3da85d604efad5c8e6f38b2
parente3f4ed7e67c9effb30fcf554fa97026857e394fa (diff)
Build language: Add str.format function.
'x{key}x'.format(key = 2) == 'x2x' It is a very simplified version of the Python format. -- MOS_MIGRATED_REVID=93130656
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java36
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java2
2 files changed, 35 insertions, 3 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java
index 07c7157fbc..4efb316113 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/MethodLibrary.java
@@ -362,6 +362,38 @@ public class MethodLibrary {
}
};
+ // In Python, formatting is very complex.
+ // We handle here the simplest case which provides most of the value of the function.
+ // https://docs.python.org/3/library/string.html#formatstrings
+ @SkylarkSignature(name = "format", objectType = StringModule.class, returnType = String.class,
+ doc = "Replace the values surrounded by curly brackets in the string."
+ + "<pre class=\"language-python\">"
+ + "\"x{key}x\".format(key = 2) == \"x2x\"</pre>\n",
+ mandatoryPositionals = {
+ @Param(name = "self", type = String.class, doc = "This string."),
+ },
+ extraKeywords = {
+ @Param(name = "kwargs", doc = "the struct fields")},
+ useLocation = true)
+ private static BuiltinFunction format = new BuiltinFunction("format") {
+ public String invoke(String self, Map<String, Object> kwargs, Location loc)
+ throws ConversionException, EvalException {
+ StringBuffer result = new StringBuffer();
+ Pattern pattern = Pattern.compile("\\{[^}]*\\}");
+ Matcher matcher = pattern.matcher(self);
+ while (matcher.find()) {
+ String word = matcher.group();
+ word = word.substring(1, word.length() - 1); // remove the curly braces
+ if (!kwargs.containsKey(word)) {
+ throw new EvalException(loc, "No replacement found for '" + word + "'");
+ }
+ matcher.appendReplacement(result, EvalUtils.printValue(kwargs.get(word)));
+ }
+ matcher.appendTail(result);
+ return result.toString();
+ }
+ };
+
@SkylarkSignature(name = "startswith", objectType = StringModule.class,
returnType = Boolean.class,
doc = "Returns True if the string starts with <code>sub</code>, "
@@ -701,7 +733,7 @@ public class MethodLibrary {
+ "<pre class=\"language-python\">s = struct(x = 2, y = 3)\n"
+ "return s.x + s.y # returns 5</pre>",
extraKeywords = {
- @Param(name = "kwarg", doc = "the struct fields")},
+ @Param(name = "kwargs", doc = "the struct fields")},
useLocation = true)
private static BuiltinFunction struct = new BuiltinFunction("struct") {
@SuppressWarnings("unchecked")
@@ -1038,7 +1070,7 @@ public class MethodLibrary {
public static final class DictModule {}
public static final List<BaseFunction> stringFunctions = ImmutableList.<BaseFunction>of(
- count, endswith, find, index, join, lower, replace, rfind,
+ count, endswith, find, index, format, join, lower, replace, rfind,
rindex, slice, split, startswith, strip, upper);
public static final List<BaseFunction> listPureFunctions = ImmutableList.<BaseFunction>of(
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
index 57371e86cd..579268fe68 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -567,7 +567,7 @@ public class SkylarkEvaluationTest extends EvaluationTest {
@Test
public void testStructPosArgs() throws Exception {
- checkEvalError("struct(**kwarg) does not accept positional arguments, but got 1",
+ checkEvalError("struct(**kwargs) does not accept positional arguments, but got 1",
"x = struct(1, b = 2)\n");
}