Skip to content

Commit 5f3b80a

Browse files
authored
Merge pull request #191 from joaoe/undefined-streams-190
Allowed PythonShell to work with unset std streams #190
2 parents 933a787 + 1b36e01 commit 5f3b80a

File tree

2 files changed

+45
-18
lines changed

2 files changed

+45
-18
lines changed

index.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -138,29 +138,37 @@ export class PythonShell extends EventEmitter{
138138

139139
['stdout', 'stdin', 'stderr'].forEach(function (name) {
140140
self[name] = self.childProcess[name];
141-
self.parser && self[name].setEncoding(options.encoding || 'utf8');
141+
self.parser && self[name] && self[name].setEncoding(options.encoding || 'utf8');
142142
});
143143

144144
// parse incoming data on stdout
145-
if (this.parser) {
145+
if (this.parser && this.stdout) {
146146
this.stdout.on('data', this.receive.bind(this));
147147
}
148148

149149
// listen to stderr and emit errors for incoming data
150-
this.stderr.on('data', function (data) {
151-
errorData += ''+data;
152-
self.receiveStderr(data);
153-
});
150+
if (this.stderr) {
151+
this.stderr.on('data', function (data) {
152+
errorData += ''+data;
153+
self.receiveStderr(data);
154+
});
154155

155-
this.stderr.on('end', function(){
156-
self.stderrHasEnded = true
157-
terminateIfNeeded();
158-
})
156+
this.stderr.on('end', function(){
157+
self.stderrHasEnded = true;
158+
terminateIfNeeded();
159+
});
160+
} else {
161+
self.stderrHasEnded = true;
162+
}
159163

160-
this.stdout.on('end', function(){
161-
self.stdoutHasEnded = true
162-
terminateIfNeeded();
163-
})
164+
if (this.stdout) {
165+
this.stdout.on('end', function(){
166+
self.stdoutHasEnded = true;
167+
terminateIfNeeded();
168+
});
169+
} else {
170+
self.stdoutHasEnded = true;
171+
}
164172

165173
this.childProcess.on('exit', function (code,signal) {
166174
self.exitCode = code;
@@ -339,6 +347,7 @@ export class PythonShell extends EventEmitter{
339347
* @returns {PythonShell} The same instance for chaining calls
340348
*/
341349
send(message:string|Object) {
350+
if (!this.stdin) throw new Error("stdin not open for writting");
342351
let data = this.formatter ? this.formatter(message) : message;
343352
if (this.mode !== 'binary') data += newline;
344353
this.stdin.write(data);
@@ -352,7 +361,7 @@ export class PythonShell extends EventEmitter{
352361
* @param {string|Buffer} data The data to parse into messages
353362
*/
354363
receive(data:string|Buffer) {
355-
return this.recieveInternal(data, 'message');
364+
return this.receiveInternal(data, 'message');
356365
};
357366

358367
/**
@@ -362,10 +371,10 @@ export class PythonShell extends EventEmitter{
362371
* @param {string|Buffer} data The data to parse into messages
363372
*/
364373
receiveStderr(data:string|Buffer) {
365-
return this.recieveInternal(data, 'stderr');
374+
return this.receiveInternal(data, 'stderr');
366375
};
367376

368-
private recieveInternal(data:string|Buffer, emitType:'message'|'stderr'){
377+
private receiveInternal(data:string|Buffer, emitType:'message'|'stderr'){
369378
let self = this;
370379
let parts = (''+data).split(new RegExp(newline,'g'));
371380

@@ -394,7 +403,9 @@ export class PythonShell extends EventEmitter{
394403
* @returns {PythonShell} The same instance for chaining calls
395404
*/
396405
end(callback:(err:PythonShellError, exitCode:number,exitSignal:string)=>any) {
397-
this.childProcess.stdin.end();
406+
if (this.childProcess.stdin) {
407+
this.childProcess.stdin.end();
408+
}
398409
this._endCallback = callback;
399410
return this;
400411
};

test/test-python-shell.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ describe('PythonShell', function () {
225225
scriptPath: pythonFolder
226226
};
227227
})
228+
229+
it('should run PythonShell normally without access to std streams', function (done) {
230+
var pyshell = PythonShell.run('exit-code.py', {
231+
// 3 different ways of assigning values to the std streams in child_process.spawn()
232+
// * ignore - pipe to /dev/null
233+
// * inherit - inherit fd from parent process;
234+
// * process.stderr - pass output directly to that stream.
235+
stdio: ['ignore', 'inherit', process.stderr],
236+
args: ["0"]
237+
}, done);
238+
239+
should(pyshell.stdin).be.eql(null);
240+
should(pyshell.stdout).be.eql(null);
241+
should(pyshell.stderr).be.eql(null);
242+
should.throws(() => {pyshell.send("asd")});
243+
});
228244
});
229245

230246
describe('.send(message)', function () {

0 commit comments

Comments
 (0)