Xiao-zhen-Liu commented on code in PR #5912:
URL: https://github.com/apache/texera/pull/5912#discussion_r3696823325


##########
common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/udf/python/PythonUDFOpDescV2.scala:
##########
@@ -91,6 +107,13 @@ class PythonUDFOpDescV2 extends LogicalOp {
   )
   var outputColumns: List[Attribute] = List()
 
+  @JsonProperty
+  @JsonSchemaTitle("Parameters")
+  @JsonPropertyDescription(
+    "Parameters inferred from active self.UiParameter(...) calls in the Python 
script"
+  )
+  var uiParameters: List[UiUDFParameter] = List()

Review Comment:
   The parser seeds new rows with an empty value, and an empty value parses to 
`0` / `False` / 1970-01-01 in the Python runtime — no warning. Combined with 
the rows not showing up in the panel, a first run can silently use 0 for a 
number the user never filled in. Worth deciding whether an empty value should 
block the run instead.
   
   Also, this same property block is repeated in all three descriptors; a small 
shared trait would keep them from drifting.



##########
frontend/src/app/workspace/component/property-editor/operator-property-edit-frame/operator-property-edit-frame.component.ts:
##########
@@ -516,6 +518,23 @@ export class OperatorPropertyEditFrameComponent implements 
OnInit, OnChanges, On
           this.currentOperatorStatus = update[this.currentOperatorId];
         }
       });
+
+    this.uiUdfParametersSyncService.uiParametersChanged$
+      .pipe(untilDestroyed(this))
+      .subscribe(({ operatorId, parameters }) => {
+        if (operatorId !== this.currentOperatorId) return;
+
+        const currentOperator = 
this.workflowActionService.getTexeraGraph().getOperator(operatorId);
+
+        const newModel = {
+          ...cloneDeep(currentOperator.operatorProperties),
+          uiParameters: cloneDeep(parameters),
+        };
+
+        this.listeningToChange = false;

Review Comment:
   Setting `listeningToChange = false` here blocks the only thing that 
refreshes the panel. Yjs observers run synchronously inside `transact`, so the 
property-change event fires before `setOperatorProperty` returns and gets 
dropped by the filter on line 714 — `formData` keeps the old list, so the new 
rows never appear until you click away and back.
   
   Worse, since `checkOperatorProperty` compares that stale `formData` against 
the graph, editing any other field afterwards writes the old list back and 
drops the parsed parameters.
   
   Refresh `formData` from the graph after the write, and consider doing the 
write inside the sync service so it doesn't depend on which panel is open.



##########
common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/udf/python/PythonUDFOpDescV2.scala:
##########
@@ -130,7 +153,7 @@ class PythonUDFOpDescV2 extends LogicalOp {
           workflowId,
           executionId,
           operatorIdentifier,
-          OpExecWithCode(code, "python")
+          OpExecWithCode(PythonUdfUiParameterInjector.inject(code, 
uiParameters), "python")

Review Comment:
   No test for the injector wiring, though `PythonUDFOpDescV2Spec` already 
asserts `OpExecWithCode(code, "python")` on this exact line — it only still 
passes because an empty list returns the code unchanged. Please add a case per 
descriptor with a non-empty list, asserting the hook shows up in the generated 
code.
   
   Small thing: `inject(...)` is called in both branches of the if/else; 
compute it once above.



##########
common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/udf/python/PythonUDFOpDescV2.scala:
##########
@@ -36,6 +36,22 @@ class PythonUDFOpDescV2 extends LogicalOp {
     required = true,
     defaultValue =
       "# Choose from the following templates:\n" +
+        "# \n" +
+        "# UiParameter notes:\n" +

Review Comment:
   Three concerns with this block: it's 16 lines of prose copy-pasted into 
three files, the example `def open(self)` sits above the class so uncommenting 
it as written won't work, and it leaves out the rule that actually breaks 
things — the class has to be named one of `ProcessTupleOperator` / 
`ProcessBatchOperator` / `ProcessTableOperator` / `GenerateOperator`, or the 
parameters silently disappear.
   
   Consider trimming this to two or three lines and putting the details in the 
operator docs. Those docs also need updating: 
`docs/reference/operators/user-defined-functions/python/*.md` still show the 
old default code and don't list the new Parameters property.



##########
frontend/src/app/workspace/component/property-editor/operator-property-edit-frame/operator-property-edit-frame.component.ts:
##########
@@ -516,6 +518,23 @@ export class OperatorPropertyEditFrameComponent implements 
OnInit, OnChanges, On
           this.currentOperatorStatus = update[this.currentOperatorId];
         }
       });
+
+    this.uiUdfParametersSyncService.uiParametersChanged$

Review Comment:
   `uiParametersChanged$` is a `ReplaySubject(1)`, so when the panel is 
destroyed and rebuilt (click blank canvas, then the operator again) this 
subscription immediately gets the last parse result and writes it again — 
including the empty values from before the user typed anything. That can 
quietly replace a value the user already entered.
   
   Worth ignoring the replayed event, or comparing against what's in the graph 
before writing.



##########
frontend/src/app/workspace/component/property-editor/operator-property-edit-frame/operator-property-edit-frame.component.scss:
##########
@@ -212,3 +212,14 @@
   padding-top: 8px;
   border-top: 1px solid #f0f0f0;
 }
+
+/* Style only the UDF Parameters field. */
+:host ::ng-deep label[for*="ui-udf-parameters"] {

Review Comment:
   Matching `label[for*="ui-udf-parameters"]` relies on Formly building an id 
that contains the widget type name, so a rename elsewhere would silently drop 
the styling. A class on the widget's own template would be sturdier. Also 
`#d1d1d1` and `1.5px` don't match the values used elsewhere in this file.



##########
frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.ts:
##########
@@ -403,6 +410,13 @@ export class CodeEditorComponent implements AfterViewInit, 
SafeStyle, OnDestroy
         }
         this.setupAIAssistantActions(editor);
         this.initCodeDebuggerComponent(editor);
+        if (this.detachYCodeListener) {
+          this.detachYCodeListener();
+        }
+
+        if (this.code) {
+          this.detachYCodeListener = 
this.uiUdfParametersSyncService.attachToYCode(this.currentOperatorId, 
this.code);

Review Comment:
   Now that the sync is turned on, nothing subscribes to 
`uiParametersParseError$`. Duplicate parameter names or two UDF classes make 
the parser throw, the sync stops early, and the user sees no message while the 
panel keeps the old rows. Worth showing that error somewhere in this PR, since 
it's the only signal the user gets before running.



-- 
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