carloea2 commented on code in PR #8346:
URL: https://github.com/apache/texera/pull/8346#discussion_r4254146091


##########
common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/polarChart/PolarChartOpDescSpec.scala:
##########
@@ -72,4 +82,129 @@ class PolarChartOpDescSpec extends AnyFlatSpec with 
Matchers {
     p.r shouldBe "radius"
     p.theta shouldBe "angle"
   }
+
+  // A source read from Arrow hands over nullable dtypes such as Int64, which
+  // np.issubdtype cannot interpret; the check must draw them, not raise.
+  "PolarChartOpDesc.generateStandaloneCode" should
+    "draw nullable numeric columns and refuse non-numeric ones" taggedAs 
NeedsPythonPackages in {
+    val python = resolvePythonExecutable().getOrElse(
+      cancel("No runnable python executable (udf.conf python.path, python3, 
python, py)")
+    )
+    if (!canImportPandasAndPlotly(python)) {
+      cancel(s"'$python' cannot import pandas and plotly; skipping runtime 
verification")
+    }
+
+    val d = new PolarChartOpDesc
+    d.r = "r"
+    d.theta = "theta"
+    val moduleFile = Files.createTempFile("polar_standalone_", ".py")
+    val driverFile = Files.createTempFile("polar_driver_", ".py")
+    try {
+      Files.write(moduleFile, 
d.generateStandaloneCode().getBytes(StandardCharsets.UTF_8))
+      Files.write(driverFile, driverScript.getBytes(StandardCharsets.UTF_8))
+
+      val process = new ProcessBuilder(python, driverFile.toString, 
moduleFile.toString)
+        .redirectErrorStream(true)
+        .start()
+      if (!process.waitFor(120, TimeUnit.SECONDS)) {
+        process.destroyForcibly()
+        fail("Polar driver timed out after 120s")
+      }
+      val output = new String(process.getInputStream.readAllBytes(), 
StandardCharsets.UTF_8)
+      withClue(s"Driver output:\n$output\n") {
+        process.exitValue() shouldBe 0
+        val verdicts = "CASE (\\S+) (\\S+)".r
+          .findAllMatchIn(output)
+          .map(m => m.group(1) -> m.group(2))
+          .toMap
+        verdicts shouldBe Map(
+          "numpy" -> "CHART",
+          "nullable" -> "CHART",
+          "boolean" -> "NOT_NUMERIC",
+          "text" -> "NOT_NUMERIC"
+        )
+      }
+    } finally {
+      Try(Files.deleteIfExists(moduleFile))
+      Try(Files.deleteIfExists(driverFile))
+      ()
+    }
+  }
+
+  // Runs the exported block over one frame per case and reports the page it
+  // wrote, so a check that raises instead of answering fails here.
+  private val driverScript: String =
+    """import pathlib
+      |import sys
+      |import tempfile
+      |
+      |import pandas as pd
+      |import plotly.graph_objects as go
+      |
+      |source = pathlib.Path(sys.argv[1]).read_text()
+      |
+      |cases = {
+      |    "numpy": pd.DataFrame({"r": [1, 2], "theta": [0, 90]}),
+      |    "nullable": pd.DataFrame(
+      |        {"r": pd.array([1, 2], dtype="Int64"), "theta": pd.array([0, 
90], dtype="Int64")}
+      |    ),
+      |    "boolean": pd.DataFrame({"r": [True, False], "theta": [0, 90]}),
+      |    "text": pd.DataFrame({"r": [1, 2], "theta": ["a", "b"]}),
+      |}
+      |
+      |for name, frame in cases.items():
+      |    directory = tempfile.mkdtemp()
+      |    scope = {
+      |        "in1df": frame,
+      |        "outputHtml": directory + "/chart.html",
+      |        "outputJson": directory + "/chart.json",
+      |        "pd": pd,
+      |        "go": go,
+      |    }
+      |    exec(compile(source, "standalone", "exec"), scope)
+      |    page = pathlib.Path(scope["outputHtml"]).read_text()

Review Comment:
   Please specify UTF-8 when reading the module and chart files. This new 
driver fails on Windows with UnicodeDecodeError while reading the valid NumPy 
control's Plotly HTML, before it reaches the nullable case. The same test 
passes with PYTHONUTF8=1, including nullable integers and the boolean and text 
rejection cases.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to