You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/08/07 19:09:31 UTC
(texera) 01/01: fix(visualization): define the render_error the table charts already call (#7260)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-7260-6daa84641094185690ec1d721f91de29635ebd93
in repository https://gitbox.apache.org/repos/asf/texera.git
commit a96bf3e70c0e9d5bf72402637633b36e99049a25
Author: Kary Zheng <15...@users.noreply.github.com>
AuthorDate: Fri Aug 7 12:09:08 2026 -0700
fix(visualization): define the render_error the table charts already call (#7260)
### What changes were proposed in this PR?
`TablesPlotOpDesc` and `FigureFactoryTableOpDesc` both generate a
`TableChartOperator` that calls `self.render_error(...)` on two
branches, but neither generated class defines that method. Each now
defines it, in the same shape the other visualization operators use.
### Why are the changes needed?
Both branches are reachable — an empty input table, and a value column
left with only non-positive or null values. Executing each operator's
generated module against an empty frame raises `AttributeError:
'TableChartOperator' object has no attribute 'render_error'` instead of
showing the message the code was written to show. With the definition
added, the same run yields `Tables Plot is not available. Reason is:
input table is empty.`
### Any related issues, documentation, discussions?
Closes #7244
### How was this PR tested?
`WorkflowOperator/scalafmtCheckAll` and both operators' descriptor specs
(14 tests). Each spec now asserts its generated class defines
`render_error` and formats the operator's name. Separately, each
generated module was run locally against an empty frame before and after
the fix, with the `pytexera` and `plotly` imports stubbed — the before
run reproduces the `AttributeError`, the after run returns `Tables Plot
is not available. Reason is: input table is empty.`
### Does this PR introduce any user-facing change?
Yes. Those two cases now render the intended message instead of failing
the operator. Nothing changes on the path that produces a chart.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)
---------
Co-authored-by: Claude Opus 5 (1M context) <no...@anthropic.com>
Co-authored-by: Xuan Gu <16...@users.noreply.github.com>
---
.../figureFactoryTable/FigureFactoryTableOpDesc.scala | 3 +++
.../operator/visualization/tablesChart/TablesPlotOpDesc.scala | 3 +++
.../figureFactoryTable/FigureFactoryTableOpDescSpec.scala | 11 +++++++++++
.../visualization/tablesChart/TablesPlotOpDescSpec.scala | 11 +++++++++++
4 files changed, 28 insertions(+)
diff --git a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDesc.scala b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDesc.scala
index ae9f9073e0..c1c94f7b12 100644
--- a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDesc.scala
+++ b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDesc.scala
@@ -104,6 +104,9 @@ class FigureFactoryTableOpDesc extends PythonOperatorDescriptor {
|
|class TableChartOperator(UDFTableOperator):
|
+ | def render_error(self, error_msg) -> str:
+ | return f"<h1>Figure Factory Table is not available.</h1><p>Reason is: {error_msg}</p>"
+ |
| def process_table(self, table: Table, port: int) -> Iterator[Optional[TableLike]]:
|
| if table.empty:
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 bf23016275..7290c057dd 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
@@ -76,6 +76,9 @@ class TablesPlotOpDesc extends PythonOperatorDescriptor {
|import plotly.io
|class TableChartOperator(UDFTableOperator):
|
+ | def render_error(self, error_msg) -> str:
+ | return f"<h1>Tables Plot is not available.</h1><p>Reason is: {error_msg}</p>"
+ |
| def process_table(self, table: Table, port: int) -> Iterator[Optional[TableLike]]:
|
| if table.empty:
diff --git a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDescSpec.scala b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDescSpec.scala
index 83eeed1f96..9d564fd358 100644
--- a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDescSpec.scala
+++ b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/figureFactoryTable/FigureFactoryTableOpDescSpec.scala
@@ -99,4 +99,15 @@ class FigureFactoryTableOpDescSpec extends AnyFlatSpec with BeforeAndAfter with
assert(carries(code, "col_two"))
code should include("class TableChartOperator(UDFTableOperator)")
}
+
+ it should "define the render_error the empty-table branches call" in {
+ // Both empty-table branches call self.render_error; without the definition they
+ // raised AttributeError instead of rendering the message.
+ withColumns()
+ val code = opDesc.generatePythonCode()
+ code should include("def render_error(self, error_msg) -> str:")
+ code should include(
+ """return f"<h1>Figure Factory Table is not available.</h1><p>Reason is: {error_msg}</p>""""
+ )
+ }
}
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 cc19113906..c088cacc67 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
@@ -88,4 +88,15 @@ class TablesPlotOpDescSpec extends AnyFlatSpec with BeforeAndAfter with Matchers
)
code should not include "')','"
}
+
+ it should "define the render_error the empty-table branches call" in {
+ // Both empty-table branches call self.render_error; without the definition they
+ // raised AttributeError instead of rendering the message.
+ opDesc.includedColumns = List(column("col_one"), column("col_two"))
+ val code = opDesc.generatePythonCode()
+ code should include("def render_error(self, error_msg) -> str:")
+ code should include(
+ """return f"<h1>Tables Plot is not available.</h1><p>Reason is: {error_msg}</p>""""
+ )
+ }
}