11""" 
2-      Models Node as a central element in a project's pipeline
2+ Models Node as a central element in a project's pipeline 
33""" 
44
55from  typing  import  Annotated , Any , TypeAlias , Union 
1717    StringConstraints ,
1818    field_validator ,
1919)
20+ from  pydantic .config  import  JsonDict 
2021
2122from  .basic_types  import  EnvVarKey , KeyIDStr 
2223from  .projects_access  import  AccessEnum 
7172
7273
7374class  NodeState (BaseModel ):
74-     modified : bool  =  Field (
75-         default = True , description = "true if the node's outputs need to be re-computed" 
76-     )
77-     dependencies : set [NodeID ] =  Field (
78-         default_factory = set ,
79-         description = "contains the node inputs dependencies if they need to be computed first" ,
80-     )
81-     current_status : RunningState  =  Field (
82-         default = RunningState .NOT_STARTED ,
83-         description = "the node's current state" ,
84-         alias = "currentStatus" ,
85-     )
86-     progress : float  |  None  =  Field (
87-         default = 0 ,
88-         ge = 0.0 ,
89-         le = 1.0 ,
90-         description = "current progress of the task if available (None if not started or not a computational task)" ,
91-     )
75+     modified : Annotated [
76+         bool ,
77+         Field (
78+             description = "true if the node's outputs need to be re-computed" ,
79+         ),
80+     ] =  True 
81+ 
82+     dependencies : Annotated [
83+         set [NodeID ],
84+         Field (
85+             default_factory = set ,
86+             description = "contains the node inputs dependencies if they need to be computed first" ,
87+         ),
88+     ] =  DEFAULT_FACTORY 
89+ 
90+     current_status : Annotated [
91+         RunningState ,
92+         Field (
93+             description = "the node's current state" ,
94+             alias = "currentStatus" ,
95+         ),
96+     ] =  RunningState .NOT_STARTED 
97+ 
98+     progress : Annotated [
99+         float  |  None ,
100+         Field (
101+             ge = 0.0 ,
102+             le = 1.0 ,
103+             description = "current progress of the task if available (None if not started or not a computational task)" ,
104+         ),
105+     ] =  0 
106+ 
92107    model_config  =  ConfigDict (
93108        extra = "forbid" ,
109+         populate_by_name = True ,
94110        json_schema_extra = {
95111            "examples" : [
96112                {
@@ -113,24 +129,35 @@ class NodeState(BaseModel):
113129    )
114130
115131
132+ def  _convert_old_enum_name (v ) ->  RunningState :
133+     if  v  ==  "FAILURE" :
134+         return  RunningState .FAILED 
135+     return  RunningState (v )
136+ 
137+ 
116138class  Node (BaseModel ):
117-     key : ServiceKey  =  Field (
118-         ...,
119-         description = "distinctive name for the node based on the docker registry path" ,
120-         examples = [
121-             "simcore/services/comp/itis/sleeper" ,
122-             "simcore/services/dynamic/3dviewer" ,
123-             "simcore/services/frontend/file-picker" ,
124-         ],
125-     )
126-     version : ServiceVersion  =  Field (
127-         ...,
128-         description = "semantic version number of the node" ,
129-         examples = ["1.0.0" , "0.0.1" ],
130-     )
131-     label : str  =  Field (
132-         ..., description = "The short name of the node" , examples = ["JupyterLab" ]
133-     )
139+     key : Annotated [
140+         ServiceKey ,
141+         Field (
142+             description = "distinctive name for the node based on the docker registry path" ,
143+             examples = [
144+                 "simcore/services/comp/itis/sleeper" ,
145+                 "simcore/services/dynamic/3dviewer" ,
146+                 "simcore/services/frontend/file-picker" ,
147+             ],
148+         ),
149+     ]
150+     version : Annotated [
151+         ServiceVersion ,
152+         Field (
153+             description = "semantic version number of the node" ,
154+             examples = ["1.0.0" , "0.0.1" ],
155+         ),
156+     ]
157+     label : Annotated [
158+         str ,
159+         Field (description = "The short name of the node" , examples = ["JupyterLab" ]),
160+     ]
134161    progress : Annotated [
135162        float  |  None ,
136163        Field (
@@ -204,9 +231,9 @@ class Node(BaseModel):
204231        Field (default_factory = dict , description = "values of output properties" ),
205232    ] =  DEFAULT_FACTORY 
206233
207-     output_node : Annotated [
208-         bool   |   None ,  Field ( deprecated = True ,  alias = "outputNode" ) 
209-     ]  =   None 
234+     output_node : Annotated [bool   |   None ,  Field ( deprecated = True ,  alias = "outputNode" )]  =  ( 
235+         None 
236+     ) 
210237
211238    output_nodes : Annotated [
212239        list [NodeID ] |  None ,
@@ -255,24 +282,109 @@ def _convert_empty_str_to_none(cls, v):
255282            return  None 
256283        return  v 
257284
258-     @classmethod  
259-     def  _convert_old_enum_name (cls , v ) ->  RunningState :
260-         if  v  ==  "FAILURE" :
261-             return  RunningState .FAILED 
262-         return  RunningState (v )
263- 
264285    @field_validator ("state" , mode = "before" ) 
265286    @classmethod  
266287    def  _convert_from_enum (cls , v ):
267288        if  isinstance (v , str ):
289+ 
268290            # the old version of state was a enum of RunningState 
269-             running_state_value  =  cls . _convert_old_enum_name (v )
270-             return  NodeState (currentStatus = running_state_value )
291+             running_state_value  =  _convert_old_enum_name (v )
292+             return  NodeState (current_status = running_state_value )
271293        return  v 
272294
295+     @staticmethod  
296+     def  _update_json_schema_extra (schema : JsonDict ) ->  None :
297+         schema .update (
298+             {
299+                 "examples" : [
300+                     # Minimal example with only required fields 
301+                     {
302+                         "key" : "simcore/services/comp/no_ports" ,
303+                         "version" : "1.0.0" ,
304+                         "label" : "Sleep" ,
305+                     },
306+                     # Complete example with optional fields 
307+                     {
308+                         "key" : "simcore/services/comp/only_inputs" ,
309+                         "version" : "1.0.0" ,
310+                         "label" : "Only INputs" ,
311+                         "inputs" : {
312+                             "input_1" : 1 ,
313+                             "input_2" : 2 ,
314+                             "input_3" : 3 ,
315+                         },
316+                     },
317+                     # Complete example with optional fields 
318+                     {
319+                         "key" : "simcore/services/comp/only_outputs" ,
320+                         "version" : "1.0.0" ,
321+                         "label" : "Only Outputs" ,
322+                         "outputs" : {
323+                             "output_1" : 1 ,
324+                             "output_2" : 2 ,
325+                             "output_3" : 3 ,
326+                         },
327+                     },
328+                     # Example with all possible input and output types 
329+                     {
330+                         "key" : "simcore/services/comp/itis/all-types" ,
331+                         "version" : "1.0.0" ,
332+                         "label" : "All Types Demo" ,
333+                         "inputs" : {
334+                             "boolean_input" : True ,
335+                             "integer_input" : 42 ,
336+                             "float_input" : 3.14159 ,
337+                             "string_input" : "text value" ,
338+                             "json_input" : {"key" : "value" , "nested" : {"data" : 123 }},
339+                             "port_link_input" : {
340+                                 "nodeUuid" : "f2700a54-adcf-45d4-9881-01ec30fd75a2" ,
341+                                 "output" : "out_1" ,
342+                             },
343+                             "simcore_file_link" : {
344+                                 "store" : "simcore.s3" ,
345+                                 "path" : "123e4567-e89b-12d3-a456-426614174000/test.csv" ,
346+                             },
347+                             "datcore_file_link" : {
348+                                 "store" : "datcore" ,
349+                                 "dataset" : "N:dataset:123" ,
350+                                 "path" : "path/to/file.txt" ,
351+                             },
352+                             "download_link" : {
353+                                 "downloadLink" : "https://example.com/downloadable/file.txt" 
354+                             },
355+                             "array_input" : [1 , 2 , 3 , 4 , 5 ],
356+                             "object_input" : {"name" : "test" , "value" : 42 },
357+                         },
358+                         "outputs" : {
359+                             "boolean_output" : False ,
360+                             "integer_output" : 100 ,
361+                             "float_output" : 2.71828 ,
362+                             "string_output" : "result text" ,
363+                             "json_output" : {"status" : "success" , "data" : [1 , 2 , 3 ]},
364+                             "simcore_file_output" : {
365+                                 "store" : "simcore.s3" ,
366+                                 "path" : "987e6543-e21b-12d3-a456-426614174000/result.csv" ,
367+                             },
368+                             "datcore_file_output" : {
369+                                 "store" : "datcore" ,
370+                                 "dataset" : "N:dataset:456" ,
371+                                 "path" : "results/output.txt" ,
372+                             },
373+                             "download_link_output" : {
374+                                 "downloadLink" : "https://example.com/results/download.txt" 
375+                             },
376+                             "array_output" : ["a" , "b" , "c" , "d" ],
377+                             "object_output" : {"status" : "complete" , "count" : 42 },
378+                         },
379+                     },
380+                 ],
381+             }
382+         )
383+ 
273384    model_config  =  ConfigDict (
274385        extra = "forbid" ,
275386        populate_by_name = True ,
387+         json_schema_extra = _update_json_schema_extra ,
276388    )
277389
278390
0 commit comments