diff --git a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDesc.scala b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDesc.scala index dcd4c399297..bf230162759 100644 --- a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDesc.scala +++ b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDesc.scala @@ -36,7 +36,10 @@ class TablesPlotOpDesc extends PythonOperatorDescriptor { var includedColumns: List[TablesConfig] = List() private def getAttributes: String = - includedColumns.map(c => pyb"""${c.attributeName}""").mkString("','") + // Join with a plain comma: each column renders to a decode_python_template(...) + // call, so joining with the literal ',' would put a string right after a call + // and produce invalid Python. + includedColumns.map(c => pyb"""${c.attributeName}""").mkString(",") def manipulateTable(): PythonTemplateBuilder = { assert(includedColumns.nonEmpty, "Included Columns cannot be empty") diff --git a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDescSpec.scala b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDescSpec.scala index ea772521094..cc191139060 100644 --- a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDescSpec.scala +++ b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/tablesChart/TablesPlotOpDescSpec.scala @@ -77,4 +77,15 @@ class TablesPlotOpDescSpec extends AnyFlatSpec with BeforeAndAfter with Matchers assert(carries(code, "col_two")) code should include("class TableChartOperator(UDFTableOperator)") } + + it should "join multiple columns with a comma, not the literal ',' (valid Python)" in { + // Each column renders to a decode(...) call, so they must be comma-joined; + // joining with the literal ',' puts a string right after a call (invalid Python). + opDesc.includedColumns = List(column("col_one"), column("col_two")) + val code = opDesc.generatePythonCode() + code should include( + s"self.decode_python_template('${b64("col_one")}'),self.decode_python_template('${b64("col_two")}')" + ) + code should not include "')','" + } }