Change getattr() behavior so 3-arg form doesn't fail when field is a method
RELNOTES: getattr()'s 3-arg form no longer raises an error when the retrieved field is a built-in method.
--
MOS_MIGRATED_REVID=137390666
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index 4245775..ee00adb 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -2060,10 +2060,10 @@
name = "getattr",
doc =
"Returns the struct's field of the given name if it exists. If not, it either returns "
- + "<code>default</code> (if specified) or raises an error. However, if there is a "
- + "method of the given name, this method always raises an error, regardless of the "
- + "presence of a default value. <code>getattr(x, \"foobar\")</code> is equivalent to "
- + "<code>x.foobar</code>."
+ + "<code>default</code> (if specified) or raises an error. Built-in methods cannot "
+ + "currently be retrieved in this way; doing so will result in an error if a "
+ + "<code>default</code> is not given. <code>getattr(x, \"foobar\")</code> is "
+ + "equivalent to <code>x.foobar</code>."
+ "<pre class=\"language-python\">getattr(ctx.attr, \"myattr\")\n"
+ "getattr(ctx.attr, \"myattr\", \"mydefault\")</pre>",
parameters = {
@@ -2091,7 +2091,7 @@
// 'Real' describes methods with structField() == false. Because DotExpression.eval
// returned null in this case, we know that structField() cannot return true.
boolean isRealMethod = hasMethod(obj, name, loc);
- if (defaultValue != Runtime.UNBOUND && !isRealMethod) {
+ if (defaultValue != Runtime.UNBOUND) {
return defaultValue;
}
throw new EvalException(
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index 98552bb..b70e1f6 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -478,7 +478,7 @@
+ "a method of that name exists";
new SkylarkTest()
.testIfExactError(msg, "getattr('a string', 'count')")
- .testIfExactError(msg, "getattr('a string', 'count', 'unused default')");
+ .testStatement("getattr('a string', 'count', 'default')", "default");
}
@Test