From eaa9248782f3f83ed7cebf417bb91769aeefea06 Mon Sep 17 00:00:00 2001 From: Carlos Ernesto Alvarez Berumen Date: Sat, 7 Mar 2026 01:35:22 -0600 Subject: [PATCH 1/2] v1 --- .../amber/pybuilder/EncodableInspector.scala | 16 +++++++++++++--- .../pybuilder/EncodableStringAnnotation.java | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala index 58bdcb649ec..9362016c72f 100644 --- a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala +++ b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala @@ -46,7 +46,7 @@ final class EncodableInspector[C <: blackbox.Context](val c: C) { // Keep this as a string so it also works if the annotation is referenced indirectly. private val encodableStringAnnotationFqn = - "org.apache.texera.amber.EncodableStringAnn" + "org.apache.texera.amber.pybuilder.EncodableStringAnnotation" /** * If we are pointing at a getter/accessor, hop to its accessed field symbol when possible. @@ -110,10 +110,20 @@ final class EncodableInspector[C <: blackbox.Context](val c: C) { val symHasAnn = rawSym != null && rawSym != NoSymbol && { val accessed = safeAccessed(rawSym) - accessed != null && accessed != NoSymbol && accessed.annotations.exists(annIsEncodableString) + accessed != null && accessed != NoSymbol && + accessed.annotations.exists(annIsEncodableString) } - symHasAnn || (tree.tpe != null && typeHasEncodableString(tree.tpe)) + val methodReturnHasAnn = + rawSym != null && rawSym != NoSymbol && (rawSym match { + case m: MethodSymbol => + typeHasEncodableString(m.typeSignature.finalResultType) + case _ => + false + }) + + symHasAnn || methodReturnHasAnn || + (tree.tpe != null && typeHasEncodableString(tree.tpe)) } def isPythonTemplateBuilderArg(argExpr: c.Expr[Any]): Boolean = { diff --git a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java index ea17e6d0130..f94c01f680a 100644 --- a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java +++ b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java @@ -29,6 +29,7 @@ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE_USE, - ElementType.LOCAL_VARIABLE + ElementType.LOCAL_VARIABLE, + ElementType.METHOD }) public @interface EncodableStringAnnotation {} \ No newline at end of file From b39711268cdeeae85f19b6643ba20e334132142e Mon Sep 17 00:00:00 2001 From: Carlos Ernesto Alvarez Berumen Date: Sat, 7 Mar 2026 01:45:33 -0600 Subject: [PATCH 2/2] v2 --- .../pybuilder/PythonTemplateBuilderSpec.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala b/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala index d2e423f810a..7347ba8c2fd 100644 --- a/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala +++ b/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala @@ -275,6 +275,22 @@ class PythonTemplateBuilderSpec extends AnyFunSuite { assert(builder.encode == "param-only") } + test("@StringUI method annotation triggers UI encoding") { + object Holder { + @EncodableStringAnnotation def uiText: String = "method" + } + val builder = pyb"${Holder.uiText}" + assert(builder.encode == decodeExpr("method")) + } + + test("@StringUI method annotation on def with parens triggers UI encoding") { + object Holder { + @EncodableStringAnnotation def uiText(): String = "method-parens" + } + val builder = pyb"${Holder.uiText()}" + assert(builder.encode == decodeExpr("method-parens")) + } + test("unannotated String does not become UI (stays raw python)") { val rawText: String = "raw" val builder = pyb"$rawText"