1
0
Эх сурвалжийг харах

select the right types
fix the submission

Fred Lefévère-Laoide 1 жил өмнө
parent
commit
8cff1175ea

+ 3 - 2
taipy/gui/extension/library.py

@@ -39,7 +39,7 @@ class ElementProperty:
 
     def __init__(
         self,
-        property_type: PropertyType,
+        property_type: t.Union[PropertyType, t.Type[_TaipyBase]],
         default_value: t.Optional[t.Any] = None,
         js_name: t.Optional[str] = None,
     ) -> None:
@@ -54,6 +54,7 @@ class ElementProperty:
                 JavaScript code.
         """
         self.default_value = default_value
+        self.property_type: t.Union[PropertyType, t.Type[_TaipyBase]]
         if property_type == PropertyType.broadcast:
             if isinstance(default_value, str):
                 self.default_value = _get_broadcast_var_name(default_value)
@@ -205,7 +206,7 @@ class Element:
             if default_attr is not None:
                 elt_built.set_value_and_default(
                     var_name=default_name,
-                    var_type=default_attr.property_type,
+                    var_type=t.cast(PropertyType, default_attr.property_type),
                     default_val=default_attr.default_value,
                     with_default=default_attr.property_type != PropertyType.data,
                 )

+ 1 - 0
taipy/gui_core/_GuiCoreLib.py

@@ -14,6 +14,7 @@ from datetime import datetime
 
 from taipy.gui import Gui, State
 from taipy.gui.extension import Element, ElementLibrary, ElementProperty, PropertyType
+from taipy.gui.utils import _TaipyBase
 
 from ..version import _get_version
 from ._adapters import _GuiCoreDatanodeAdapter, _GuiCoreScenarioAdapter, _GuiCoreScenarioDagAdapter

+ 61 - 29
taipy/gui_core/_context.py

@@ -24,13 +24,26 @@ import pandas as pd
 from dateutil import parser
 
 from taipy.config import Config
-from taipy.core import Cycle, DataNode, Job, Scenario, Sequence, cancel_job, create_scenario
+from taipy.core import (
+    Cycle,
+    DataNode,
+    DataNodeId,
+    Job,
+    JobId,
+    Scenario,
+    ScenarioId,
+    Sequence,
+    SequenceId,
+    cancel_job,
+    create_scenario,
+)
 from taipy.core import delete as core_delete
 from taipy.core import delete_job
 from taipy.core import get as core_get
 from taipy.core import (
     get_cycles_scenarios,
     get_data_nodes,
+    get_jobs,
     is_deletable,
     is_editable,
     is_promotable,
@@ -44,6 +57,7 @@ from taipy.core.notification import CoreEventConsumerBase, EventEntityType
 from taipy.core.notification.event import Event, EventOperation
 from taipy.core.notification.notifier import Notifier
 from taipy.core.submission.submission import Submission
+from taipy.core.submission._submission_manager_factory import _SubmissionManagerFactory
 from taipy.core.submission.submission_status import SubmissionStatus
 from taipy.gui import Gui, State
 from taipy.gui._warnings import _warn
@@ -111,17 +125,19 @@ class _GuiCoreContext(CoreEventConsumerBase):
     def process_event(self, event: Event):
         if event.entity_type == EventEntityType.SCENARIO:
             if event.operation == EventOperation.SUBMISSION:
-                self.scenario_status_callback(event.attribute_name, True)
+                self.scenario_status_callback(event.attribute_name)
                 return
             self.scenario_refresh(
-                event.entity_id if event.operation != EventOperation.DELETION and is_readable(event.entity_id) else None
+                event.entity_id
+                if event.operation != EventOperation.DELETION and is_readable(t.cast(ScenarioId, event.entity_id))
+                else None
             )
         elif event.entity_type == EventEntityType.SEQUENCE and event.entity_id:
             sequence = None
             try:
                 sequence = (
                     core_get(event.entity_id)
-                    if event.operation != EventOperation.DELETION and is_readable(event.entity_id)
+                    if event.operation != EventOperation.DELETION and is_readable(t.cast(SequenceId, event.entity_id))
                     else None
                 )
                 if sequence and hasattr(sequence, "parent_ids") and sequence.parent_ids:
@@ -130,6 +146,9 @@ class _GuiCoreContext(CoreEventConsumerBase):
                     )
             except Exception as e:
                 _warn(f"Access to sequence {event.entity_id} failed", e)
+        elif event.entity_type == EventEntityType.JOB:
+            with self.lock:
+                self.jobs_list = None
         elif event.entity_type == EventEntityType.SUBMISSION:
             self.scenario_status_callback(event.entity_id)
         elif event.entity_type == EventEntityType.DATA_NODE:
@@ -149,18 +168,16 @@ class _GuiCoreContext(CoreEventConsumerBase):
             {"scenario": scenario_id or True},
         )
 
-    def scenario_status_callback(self, submission_id: str, is_submission: t.Optional[bool] = False):
-        if not submission_id or not (is_submission or is_readable(submission_id)):
+    def scenario_status_callback(self, submission_id: t.Optional[str]):
+        if not submission_id or not is_readable_submission(submission_id):
             return
         try:
-            if is_submission:
-                sub_id = submission_id
-                submission = None
-            else:
-                submission: Submission = core_get(submission_id)
-            sub_details: t.Optional[_SubmissionDetails] = self.client_submission.get(sub_id)
+            sub_details: t.Optional[_SubmissionDetails] = self.client_submission.get(submission_id)
+            if not sub_details:
+                return
 
-            if not submission or not submission.entity_id or sub_details:
+            submission = core_get_submission(submission_id)
+            if not submission or not submission.entity_id:
                 return
 
             entity = core_get(submission.entity_id)
@@ -182,12 +199,12 @@ class _GuiCoreContext(CoreEventConsumerBase):
                     SubmissionStatus.FAILED,
                     SubmissionStatus.CANCELED,
                 ):
-                    self.client_submission.pop(sub_id, None)
+                    self.client_submission.pop(submission_id, None)
                 else:
-                    self.client_submission[sub_id] = sub_details.set_submission(new_status)
+                    self.client_submission[submission_id] = sub_details.set_submission(submission)
 
         except Exception as e:
-            _warn(f"Job ({submission_id}) is not available", e)
+            _warn(f"Submission ({submission_id}) is not available", e)
 
         finally:
             self.gui._broadcast(_GuiCoreContext._CORE_CHANGED_NAME, {"jobs": True})
@@ -243,10 +260,10 @@ class _GuiCoreContext(CoreEventConsumerBase):
         state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ID_VAR, args[0])
 
     def get_scenario_by_id(self, id: str) -> t.Optional[Scenario]:
-        if not id or not is_readable(id):
+        if not id or not is_readable(t.cast(ScenarioId, id)):
             return None
         try:
-            return core_get(id)
+            return core_get(t.cast(ScenarioId, id))
         except Exception:
             return None
 
@@ -417,14 +434,14 @@ class _GuiCoreContext(CoreEventConsumerBase):
         if entity:
             try:
                 jobs = core_submit(entity)
+                submission_entity = core_get_submission(jobs[0].submit_id if isinstance(jobs, list) else jobs.submit_id)
                 if submission_cb := data.get("on_submission_change"):
                     submission_fn = self.gui._get_user_function(submission_cb)
                     if callable(submission_fn):
-                        submission_entity = core_get(jobs[0].submit_id if isinstance(jobs, list) else jobs.submit_id)
                         client_id = self.gui._get_client_id()
                         module_context = self.gui._get_locals_context()
                         with self.submissions_lock:
-                            self.client_submission[submission_entity.submit_entity_id] = _SubmissionDetails(
+                            self.client_submission[submission_entity.id] = _SubmissionDetails(
                                 client_id,
                                 module_context,
                                 submission_fn,
@@ -490,6 +507,12 @@ class _GuiCoreContext(CoreEventConsumerBase):
 
         return None
 
+    def get_jobs_list(self):
+        with self.lock:
+            if self.jobs_list is None:
+                self.jobs_list = get_jobs()
+            return self.jobs_list
+
     def job_adapter(self, job):
         try:
             if hasattr(job, "id") and is_readable(job.id) and core_get(job.id) is not None:
@@ -617,10 +640,10 @@ class _GuiCoreContext(CoreEventConsumerBase):
                             cycles_scenarios.extend(scenarios)
                         else:
                             cycles_scenarios.append(cycle)
-                elif is_readable(owner_id):
+                elif is_readable(t.cast(ScenarioId, owner_id)):
                     entity = core_get(owner_id)
-                    if entity and (scenarios := self.scenario_by_cycle.get(entity)):
-                        cycles_scenarios.extend(scenarios)
+                    if entity and (scenarios_cycle := self.scenario_by_cycle.get(t.cast(Cycle, entity))):
+                        cycles_scenarios.extend(scenarios_cycle)
                     elif isinstance(entity, Scenario):
                         cycles_scenarios.append(entity)
         return cycles_scenarios
@@ -636,7 +659,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
             res = []
             for e in dn.edits:
                 job_id = e.get("job_id")
-                job: Job = None
+                job: t.Optional[Job] = None
                 if job_id:
                     if not is_readable(job_id):
                         job_id += " not readable"
@@ -685,10 +708,10 @@ class _GuiCoreContext(CoreEventConsumerBase):
         return _DoNotUpdate()
 
     def __check_readable_editable(self, state: State, id: str, type: str, var: str):
-        if not is_readable(id):
+        if not is_readable(t.cast(DataNodeId, id)):
             state.assign(var, f"{type} {id} is not readable.")
             return False
-        if not is_editable(id):
+        if not is_editable(t.cast(DataNodeId, id)):
             state.assign(var, f"{type} {id} is not editable.")
             return False
         return True
@@ -759,7 +782,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
             id
             and isinstance(datanode, DataNode)
             and id == datanode.id
-            and is_readable(id)
+            and is_readable(t.cast(DataNodeId, id))
             and (dn := core_get(id))
             and isinstance(dn, DataNode)
             and dn.is_ready_for_reading
@@ -775,7 +798,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
             id
             and isinstance(datanode, DataNode)
             and id == datanode.id
-            and is_readable(id)
+            and is_readable(t.cast(DataNodeId, id))
             and (dn := core_get(id))
             and isinstance(dn, DataNode)
             and dn.is_ready_for_reading
@@ -793,7 +816,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
             id
             and isinstance(datanode, DataNode)
             and id == datanode.id
-            and is_readable(id)
+            and is_readable(t.cast(DataNodeId, id))
             and (dn := core_get(id))
             and isinstance(dn, DataNode)
             and dn.is_ready_for_reading
@@ -819,3 +842,12 @@ class _GuiCoreContext(CoreEventConsumerBase):
             state.assign(_GuiCoreContext._DATANODE_VIZ_DATA_ID_VAR, data_id)
         elif chart_id := data.get("chart_id"):
             state.assign(_GuiCoreContext._DATANODE_VIZ_DATA_CHART_ID_VAR, chart_id)
+
+
+# TODO remove when Submission is supported by Core API
+def is_readable_submission(id: str):
+    return _SubmissionManagerFactory._build_manager()._is_readable(t.cast(Submission, id))
+
+
+def core_get_submission(id: str):
+    return _SubmissionManagerFactory._build_manager()._get(id)