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-7297-3db59556471eb846ffbd41726dde97b25b73f4cc
in repository https://gitbox.apache.org/repos/asf/texera.git

commit 7a79db153e9aeaafd6120805838f56e05c702ae8
Author: Prateek Ganigi <[email protected]>
AuthorDate: Wed Aug 5 12:24:11 2026 -0700

    fix(workflow-operator): raise ValueError for HF config checks instead of 
assert (stripped under -O) (#7297)
    
    ### What changes were proposed in this PR?
    
    The HuggingFace operator's pre-loop config validations (prompt column,
    zero-shot candidate labels, question-answering context column,
    sentence-similarity/text-ranking sentences column) used Python `assert`.
    That has two problems: `assert` is **stripped entirely under `python
    -O`**, silently disabling the checks, and it raises `AssertionError`
    instead of the `ValueError` used elsewhere in the operator.
    
    This converts the four `assert X, (msg)` checks to `if not X: raise
    ValueError(msg)`. Behavior is otherwise identical, same messages, same
    fail-fast on misconfiguration, but the checks now survive `-O` and raise
    a consistent error type.
    
    This is the `assert`->`ValueError` half of #7199. The other half is
    `zero-shot-image-classification` raising a `ValueError` inside the
    per-row loop (which crashes the operator rather than writing a per-row
    error), is left as a follow-up, since it needs a structural change and a
    separate design decision.
    
    ### Any related issues, documentation, discussions?
    
    Addresses #7199 (the `assert`->`ValueError` part; the zero-shot
    per-row-crash follow-up remains).
    
    ### How was this PR tested?
    
    `sbt "WorkflowOperator/testOnly
    org.apache.texera.amber.operator.huggingFace.*
    org.apache.texera.amber.util.PythonCodeRawInvalidTextSpec"`: passes (126
    tests). Added a test asserting the generated script contains no `assert
    ` and uses the explicit `raise ValueError` form;
    `PythonCodeRawInvalidTextSpec` py-compiles the generated Python (guards
    the multi-line indentation change). scalafmt clean.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    This PR was co-authored with Claude Opus 4.8 in compliance with ASF
    policy.
---
 .../codegen/HuggingFaceCodegenBase.scala           | 36 ++++++++++++----------
 .../HuggingFaceInferenceOpDescSpec.scala           | 11 +++++++
 2 files changed, 31 insertions(+), 16 deletions(-)

diff --git 
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/HuggingFaceCodegenBase.scala
 
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/HuggingFaceCodegenBase.scala
index 7db809a07a..9b59ce6d92 100644
--- 
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/HuggingFaceCodegenBase.scala
+++ 
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/HuggingFaceCodegenBase.scala
@@ -504,28 +504,32 @@ object HuggingFaceCodegenBase {
        |
        |        # --- validate prompt column exists (skipped for image tasks 
and binary-only audio tasks) ---
        |        if task not in image_tasks and task not in audio_only_tasks:
-       |            assert prompt_col in table.columns, (
-       |                f"Prompt column '{prompt_col}' not found in input 
table. "
-       |                f"Available columns: {list(table.columns)}"
-       |            )
+       |            if prompt_col not in table.columns:
+       |                raise ValueError(
+       |                    f"Prompt column '{prompt_col}' not found in input 
table. "
+       |                    f"Available columns: {list(table.columns)}"
+       |                )
        |        if task == "zero-shot-classification":
        |            labels = [l.strip() for l in 
str(self.CANDIDATE_LABELS).split(",") if l.strip()]
-       |            assert labels, (
-       |                "Candidate Labels are required for 
zero-shot-classification. "
-       |                "Provide a comma-separated list of labels."
-       |            )
+       |            if not labels:
+       |                raise ValueError(
+       |                    "Candidate Labels are required for 
zero-shot-classification. "
+       |                    "Provide a comma-separated list of labels."
+       |                )
        |        if task == "question-answering":
        |            ctx_col = self.CONTEXT_COLUMN
-       |            assert ctx_col and ctx_col in table.columns, (
-       |                f"Context column '{ctx_col}' not found in input table. 
"
-       |                f"Available columns: {list(table.columns)}"
-       |            )
+       |            if not (ctx_col and ctx_col in table.columns):
+       |                raise ValueError(
+       |                    f"Context column '{ctx_col}' not found in input 
table. "
+       |                    f"Available columns: {list(table.columns)}"
+       |                )
        |        if task in ("sentence-similarity", "text-ranking"):
        |            sent_col = self.SENTENCES_COLUMN
-       |            assert sent_col and sent_col in table.columns, (
-       |                f"Sentences column '{sent_col}' not found in input 
table. "
-       |                f"Available columns: {list(table.columns)}"
-       |            )
+       |            if not (sent_col and sent_col in table.columns):
+       |                raise ValueError(
+       |                    f"Sentences column '{sent_col}' not found in input 
table. "
+       |                    f"Available columns: {list(table.columns)}"
+       |                )
        |
        |        # --- handle empty table ---
        |        if table.empty:
diff --git 
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
 
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
index d34a6e8fea..b6b0355435 100644
--- 
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
+++ 
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
@@ -649,6 +649,17 @@ class HuggingFaceInferenceOpDescSpec extends AnyFlatSpec 
with Matchers {
     outSchema.getAttributeNames.contains("hf_response") shouldBe true
   }
 
+  it should "validate config with raise ValueError rather than assert (which 
python -O strips)" in {
+    val code = makeDesc().generatePythonCode()
+    // No `assert` in the generated script — asserts are removed under `python 
-O`,
+    // silently disabling the checks, and raise AssertionError rather than 
ValueError.
+    code should not include ("assert ")
+    // The pre-loop config checks now raise ValueError explicitly.
+    code should include("if prompt_col not in table.columns:")
+    code should include("if not (ctx_col and ctx_col in table.columns):")
+    code should include("if not (sent_col and sent_col in table.columns):")
+  }
+
   it should "validate base64 in the binary-column fallback so plain text isn't 
decoded to garbage" in {
     val code = makeDesc().generatePythonCode()
     // validate=True makes b64decode reject non-base64 input, so real text 
falls

Reply via email to