Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 29 additions & 18 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,29 +138,37 @@ export class PythonShell extends EventEmitter{

['stdout', 'stdin', 'stderr'].forEach(function (name) {
self[name] = self.childProcess[name];
self.parser && self[name].setEncoding(options.encoding || 'utf8');
self.parser && self[name] && self[name].setEncoding(options.encoding || 'utf8');
});

// parse incoming data on stdout
if (this.parser) {
if (this.parser && this.stdout) {
this.stdout.on('data', this.receive.bind(this));
}

// listen to stderr and emit errors for incoming data
this.stderr.on('data', function (data) {
errorData += ''+data;
self.receiveStderr(data);
});
if (this.stderr) {
this.stderr.on('data', function (data) {
errorData += ''+data;
self.receiveStderr(data);
});

this.stderr.on('end', function(){
self.stderrHasEnded = true
terminateIfNeeded();
})
this.stderr.on('end', function(){
self.stderrHasEnded = true;
terminateIfNeeded();
});
} else {
self.stderrHasEnded = true;
}

this.stdout.on('end', function(){
self.stdoutHasEnded = true
terminateIfNeeded();
})
if (this.stdout) {
this.stdout.on('end', function(){
self.stdoutHasEnded = true;
terminateIfNeeded();
});
} else {
self.stdoutHasEnded = true;
}

this.childProcess.on('exit', function (code,signal) {
self.exitCode = code;
Expand Down Expand Up @@ -339,6 +347,7 @@ export class PythonShell extends EventEmitter{
* @returns {PythonShell} The same instance for chaining calls
*/
send(message:string|Object) {
if (!this.stdin) throw new Error("stdin not open for writting");
let data = this.formatter ? this.formatter(message) : message;
if (this.mode !== 'binary') data += newline;
this.stdin.write(data);
Expand All @@ -352,7 +361,7 @@ export class PythonShell extends EventEmitter{
* @param {string|Buffer} data The data to parse into messages
*/
receive(data:string|Buffer) {
return this.recieveInternal(data, 'message');
return this.receiveInternal(data, 'message');
};

/**
Expand All @@ -362,10 +371,10 @@ export class PythonShell extends EventEmitter{
* @param {string|Buffer} data The data to parse into messages
*/
receiveStderr(data:string|Buffer) {
return this.recieveInternal(data, 'stderr');
return this.receiveInternal(data, 'stderr');
};

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

Expand Down Expand Up @@ -394,7 +403,9 @@ export class PythonShell extends EventEmitter{
* @returns {PythonShell} The same instance for chaining calls
*/
end(callback:(err:PythonShellError, exitCode:number,exitSignal:string)=>any) {
this.childProcess.stdin.end();
if (this.childProcess.stdin) {
this.childProcess.stdin.end();
}
this._endCallback = callback;
return this;
};
Expand Down
16 changes: 16 additions & 0 deletions test/test-python-shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,22 @@ describe('PythonShell', function () {
scriptPath: pythonFolder
};
})

it('should run PythonShell normally without access to std streams', function (done) {
var pyshell = PythonShell.run('exit-code.py', {
// 3 different ways of assigning values to the std streams in child_process.spawn()
// * ignore - pipe to /dev/null
// * inherit - inherit fd from parent process;
// * process.stderr - pass output directly to that stream.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stdio: ['ignore', 'inherit', process.stderr],
args: ["0"]
}, done);

should(pyshell.stdin).be.eql(null);
should(pyshell.stdout).be.eql(null);
should(pyshell.stderr).be.eql(null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is stdout and stderr null? Because these both inherit the parent's stdout / stderr shouldn't they have a value?

Copy link
Contributor Author

@joaoe joaoe Aug 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should be null. The underlying code does a file descriptor dup() so the child process just inherits the file descriptors directly and then all output goes to /dev/tty (for instance, if you are working in a terminal) bypassing any streams in memory in the local process (in the case of using inherit).

should.throws(() => {pyshell.send("asd")});
});
});

describe('.send(message)', function () {
Expand Down