From aa83c3aaffc4c55b6cb8adec88456903321ceecc Mon Sep 17 00:00:00 2001 From: Laurent Le Brun Date: Fri, 8 May 2015 15:00:35 +0000 Subject: 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 --- .../devtools/build/lib/packages/MethodLibrary.java | 36 ++++++++++++++++++++-- .../build/lib/syntax/SkylarkEvaluationTest.java | 2 +- 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." + + "
"
+          + "\"x{key}x\".format(key = 2) == \"x2x\"
\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 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 sub, " @@ -701,7 +733,7 @@ public class MethodLibrary { + "
s = struct(x = 2, y = 3)\n"
       + "return s.x + s.y  # returns 5
", 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 stringFunctions = ImmutableList.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 listPureFunctions = ImmutableList.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"); } -- cgit v1.2.3