6
6
exports . version = '2' ;
7
7
exports . icon = 'ti ti-script' ;
8
8
exports . author = 'Total.js' ;
9
- exports . config = { code : '# Python code\nimport sys\nimport json\n\ndata = json.loads(sys.argv[1])\n\nprint(data)' , json : true } ;
9
+ exports . config = { code : `# Python code
10
+ import sys
11
+ import json
12
+
13
+ # For non-persistent data:
14
+ data = json.loads(sys.argv[1])
15
+ print(data)
16
+
17
+ # Or for persistent data:
18
+ while True:
19
+ \tline = sys.stdin.readline().strip()
20
+ \tif not line:
21
+ \t\tbreak
22
+ \tprint(line)
23
+ \tsys.stdout.flush()
24
+ ` , json : true , persistent : false } ;
10
25
exports . inputs = [ { id : 'input' , name : 'Input' } ] ;
11
26
exports . outputs = [ { id : 'output' , name : 'Output' } , { id : 'error' , name : 'Error' } ] ;
12
27
exports . meta = { settingswidth : 1200 } ;
18
33
exports . make = function ( instance , config ) {
19
34
20
35
var filename = PATH . temp ( instance . id + '.py' ) ;
36
+ var spawned = null ;
21
37
22
38
instance . message = function ( $ ) {
23
39
26
42
return ;
27
43
}
28
44
29
- F . Child . execFile ( 'python3' , [ filename , JSON . stringify ( $ . data ) ] , function ( err , response , error ) {
30
- if ( err ) {
31
- $ . send ( 'error' , error || err ) ;
32
- } else {
33
- $ . send ( 'output' , config . json ? response . parseJSON ( true ) : response ) ;
34
- }
35
- } ) ;
45
+ if ( config . persistent ) {
46
+ if ( spawned )
47
+ spawned . stdin . write ( JSON . stringify ( $ . data ) + '\n' ) ;
48
+ $ . destroy ( ) ;
49
+ } else {
50
+ F . Child . execFile ( 'python3' , [ filename , JSON . stringify ( $ . data ) ] , function ( err , response , error ) {
51
+ if ( err ) {
52
+ $ . send ( 'error' , error || err ) ;
53
+ } else {
54
+ $ . send ( 'output' , config . json ? response . parseJSON ( true ) : response ) ;
55
+ }
56
+ } ) ;
57
+ }
36
58
} ;
37
59
38
60
instance . configure = function ( ) {
61
+
39
62
if ( config . code )
40
63
F . Fs . writeFile ( filename , config . code , err => err && instance . throw ( err ) ) ;
64
+
65
+ let ready = false ;
66
+ let prev = spawned ;
67
+
68
+ if ( spawned ) {
69
+ spawned . removeAllListeners ( 'close' ) ;
70
+ spawned . removeAllListeners ( 'error' ) ;
71
+ spawned . kill ( 9 ) ;
72
+ }
73
+
74
+ if ( config . persistent && config . code ) {
75
+
76
+ spawned = F . Child . spawn ( 'python3' , [ filename ] , { stdio : [ 'pipe' , 'pipe' , process . stderr ] } ) ; //, { stdio: 'inherit' }
77
+
78
+ spawned . on ( 'error' , function ( err ) {
79
+ instance . newmessage ( err . toString ( ) ) . send ( 'error' ) ;
80
+ } ) ;
81
+
82
+ spawned . stdout . on ( 'data' , function ( chunk ) {
83
+ let text = chunk . toString ( 'utf8' ) ;
84
+ if ( config . json )
85
+ instance . newmessage ( text . parseJSON ( true ) ) . send ( 'output' ) ;
86
+ else
87
+ instance . newmessage ( text ) . send ( 'output' ) ;
88
+ } ) ;
89
+
90
+ spawned . on ( 'close' , function ( code ) {
91
+ if ( this == spawned )
92
+ spawned = null ;
93
+ instance . status ( 'Exited: ' + code ) ;
94
+ } ) ;
95
+
96
+ instance . status ( 'Running' ) ;
97
+
98
+ } else if ( spawned ) {
99
+ spawned . kill ( 9 ) ;
100
+ spawned = null ;
101
+ ready = true ;
102
+ } else
103
+ ready = true ;
104
+
105
+ ready && instance . status ( 'Ready' ) ;
41
106
} ;
42
107
43
108
instance . configure ( ) ;
47
112
</ script >
48
113
49
114
< readme >
50
- This component executes a custom Python code as it is.
115
+ This component executes custom Python code as is. The input data must be a serializable JSON object. Non-persistent mode evaluates the Python code for each input.
116
+
117
+ The persistent mode can include an HTTP server or an infinite loop. Input data is sent to the `stdin` stream in serialized JSON format.
118
+
119
+ > __Good to know__: The output message in persistent mode doesn't container the previous message reference.
51
120
</ readme >
52
121
53
122
< settings >
54
123
< div class ="padding ">
55
- < ui-component name ="codemirror " path ="?.code " config ="type:python;minheight:300;parent:auto;margin:80 ;tabs:true;trim:true " class ="m "> </ ui-component >
124
+ < ui-component name ="codemirror " path ="?.code " config ="type:python;minheight:300;parent:auto;margin:100 ;tabs:true;trim:true " class ="m "> </ ui-component >
56
125
< ui-component name ="input " path ="?.json " config ="type:checkbox "> Parse output to JSON</ ui-component >
126
+ < ui-component name ="input " path ="?.persistent " config ="type:checkbox "> Run the script as a persistent process</ ui-component >
57
127
</ div >
58
128
</ settings >
59
129
60
130
< body >
61
131
< header >
62
- < i class ="ICON "> </ i > NAME
132
+ < i class ="$ ICON "> </ i > $ NAME
63
133
</ header >
134
+ < footer style ="padding:10px " class ="fs12 ">
135
+ < ui-bind path ="$STATUS " config ="text;empty " child ="b " class ="block "> Status: < b > </ b > </ ui-bind >
136
+ </ footer >
64
137
</ body >
0 commit comments