Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 304da70

Browse files
authored
Merge pull request #282 from extrabacon/test_pr
v5 release
2 parents 56f8d1f + 91f1097 commit 304da70

File tree

6 files changed

+79
-91
lines changed

6 files changed

+79
-91
lines changed

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## [5.0.0] - 2023年02月10日
2+
### BREAKING CHANGES
3+
- run and runString now return a promise instead of a using a callback.
4+
- You will need to 1) check the return value, 2) remove the callback argument, and 3) change to a promise
5+
- see readme for usage examples
6+
7+
### Other notes
8+
- I confirmed that python-shell works with python 3.11 and node v18.
9+
110
## [4.0.0] - 2023年02月10日
211
### Changed
312
- run and runString now return a promise instead of a using a callback.

‎README.md‎

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ npm install python-shell
2727
```typescript
2828
import {PythonShell} from 'python-shell';
2929

30-
PythonShell.runString('x=1+1;print(x)', null, function (err) {
31-
if (err) throw err;
30+
PythonShell.runString('x=1+1;print(x)', null).then(messages=>{
3231
console.log('finished');
3332
});
3433
```
@@ -47,8 +46,7 @@ let {PythonShell} = require('python-shell')
4746
```typescript
4847
import {PythonShell} from 'python-shell';
4948

50-
PythonShell.run('my_script.py', null, function (err) {
51-
if (err) throw err;
49+
PythonShell.run('my_script.py', null).then(messages=>{
5250
console.log('finished');
5351
});
5452
```
@@ -68,8 +66,7 @@ let options = {
6866
args: ['value1', 'value2', 'value3']
6967
};
7068

71-
PythonShell.run('my_script.py', options, function (err, results) {
72-
if (err) throw err;
69+
PythonShell.run('my_script.py', options).then(messages=>{
7370
// results is an array consisting of messages collected during execution
7471
console.log('results: %j', results);
7572
});
@@ -205,32 +202,28 @@ Example:
205202
PythonShell.defaultOptions = { scriptPath: '../scripts' };
206203
```
207204

208-
#### `#run(script, options, callback)`
209-
210-
Runs the Python script and invokes `callback` with the results. The callback contains the execution error (if any) as well as an array of messages emitted from the Python script.
205+
#### `#run(script, options)`
211206

212-
This method is also returning the `PythonShell` instance.
207+
Runs the Python script and returns a promise. When you handle the promise the argument will be an array of messages emitted from the Python script.
213208

214209
Example:
215210

216211
```typescript
217212
// run a simple script
218-
PythonShell.run('script.py', null, function (err, results) {
213+
PythonShell.run('script.py', null).then(results=> {
219214
// script finished
220215
});
221216
```
222217

223-
#### `#runString(code, options, callback)`
218+
#### `#runString(code, options)`
224219

225-
Runs the Python code and invokes `callback` with the results. The callback contains the execution error (if any) as well as an array of messages emitted from the Python script.
226-
227-
This method is also returning the `PythonShell` instance.
220+
Runs the Python script and returns a promise. When you handle the promise the argument will be an array of messages emitted from the Python script.
228221

229222
Example:
230223

231224
```typescript
232-
// run a simple script
233-
PythonShell.runString('x=1;print(x)', null, function (err, results) {
225+
// run some simple code
226+
PythonShell.runString('x=1;print(x)', null).then(messages=>{
234227
// script finished
235228
});
236229
```
@@ -247,7 +240,7 @@ Promise is rejected if there is a syntax error.
247240

248241
#### `#getVersion(pythonPath?:string)`
249242

250-
Returns the python version. Optional pythonPath param to get the version
243+
Returns the python version as a promise. Optional pythonPath param to get the version
251244
of a specific python interpreter.
252245

253246
#### `#getVersionSync(pythonPath?:string)`

‎index.ts‎

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ export class PythonShellError extends Error {
6767
exitCode?: number;
6868
}
6969

70+
export class PythonShellErrorWithLogs extends PythonShellError {
71+
logs: any[]
72+
}
73+
7074
/**
7175
* Takes in a string stream and emits batches seperated by newlines
7276
*/
@@ -306,62 +310,44 @@ export class PythonShell extends EventEmitter {
306310
}
307311

308312
/**
309-
* Runs a Python script and returns collected messages
310-
* @param {string} scriptPath The path to the script to execute
311-
* @param {Options} options The execution options
312-
* @param {Function} (deprecated argument) callback The callback function to invoke with the script results
313-
* @return {Promise<string[]> | PythonShell} the output from the python script
313+
* Runs a Python script and returns collected messages as a promise.
314+
* If the promise is rejected, the err will probably be of type PythonShellErrorWithLogs
315+
* @param scriptPath The path to the script to execute
316+
* @param options The execution options
314317
*/
315-
static run(scriptPath: string, options?: Options, callback?: (err?: PythonShellError, output?: any[]) => any) {
316-
317-
if(callback) {
318-
console.warn('PythonShell.run() callback is deprecated. Use PythonShell.run() promise instead.')
319-
320-
return this.runLegacy(scriptPath, options, callback);
321-
}
322-
else {
323-
return new Promise((resolve, reject) => {
324-
let pyshell = new PythonShell(scriptPath, options);
325-
let output = [];
326-
327-
pyshell.on('message', function (message) {
328-
output.push(message);
329-
}).end(function (err) {
330-
if(err) reject(err);
331-
else resolve(output);
332-
});
318+
static run(scriptPath: string, options?: Options): Promise<any[]> {
319+
return new Promise((resolve, reject) => {
320+
let pyshell = new PythonShell(scriptPath, options);
321+
let output = [];
322+
323+
pyshell.on('message', function (message) {
324+
output.push(message);
325+
}).end(function (err) {
326+
if(err){
327+
(err as PythonShellErrorWithLogs).logs = output
328+
reject(err);
329+
}
330+
else resolve(output);
333331
});
334-
}
335-
};
336-
337-
private static runLegacy(scriptPath: string, options?: Options, callback?: (err?: PythonShellError, output?: any[]) => any) {
338-
let pyshell = new PythonShell(scriptPath, options);
339-
let output = [];
340-
341-
return pyshell.on('message', function (message) {
342-
output.push(message);
343-
}).end(function (err) {
344-
return callback(err ? err : null, output.length ? output : null);
345332
});
346333
};
347334

348335

349336

350337
/**
351-
* Runs the inputted string of python code and returns collected messages. DO NOT ALLOW UNTRUSTED USER INPUT HERE!
352-
* @param {string} code The python code to execute
353-
* @param {Options} options The execution options
354-
* @param {Function} callback The callback function to invoke with the script results
355-
* @return {PythonShell} The PythonShell instance
338+
* Runs the inputted string of python code and returns collected messages as a promise. DO NOT ALLOW UNTRUSTED USER INPUT HERE!
339+
* @param code The python code to execute
340+
* @param options The execution options
341+
* @return a promise with the output from the python script
356342
*/
357-
static runString(code: string, options?: Options,callback?: (err: PythonShellError,output?: any[])=>any) {
343+
static runString(code: string, options?: Options) {
358344

359345
// put code in temp file
360346
const randomInt = getRandomInt();
361347
const filePath = tmpdir + sep + `pythonShellFile${randomInt}.py`
362348
writeFileSync(filePath, code);
363349

364-
return PythonShell.run(filePath, options,callback);
350+
return PythonShell.run(filePath, options);
365351
};
366352

367353
static getVersion(pythonPath?: string) {

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
{
22
"name": "python-shell",
3-
"version": "4.0.0",
3+
"version": "5.0.0",
44
"description": "Run Python scripts from Node.js with simple (but efficient) inter-process communication through stdio",
55
"keywords": [
66
"python"
77
],
88
"scripts": {
99
"test": "tsc -p ./ && mocha -r ts-node/register",
1010
"appveyorTest": "tsc -p ./ && nyc mocha --reporter mocha-appveyor-reporter test/*.js",
11-
"compile": "tsc -watch -p ./"
11+
"compile": "tsc -watch -p ./",
12+
"compileOnce": "tsc -p ./"
1213
},
1314
"devDependencies": {
1415
"@types/mocha": "^8.2.1",

‎test/test-python-shell.ts‎

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,23 @@ describe('PythonShell', function () {
117117
before(() => {
118118
PythonShell.defaultOptions = {};
119119
})
120-
it('should be able to execute a string of python code using callbacks', function (done) {
121-
let pythonshell = PythonShell.runString('print("hello");print("world")', null, function (err, results) {
122-
if (err) return done(err);
120+
it('should be able to execute a string of python code', function (done) {
121+
PythonShell.runString('print("hello");print("world")', null).then((results) => {
123122
results.should.be.an.Array().and.have.lengthOf(2);
124123
results.should.eql(['hello', 'world']);
125124
done();
126125
});
127-
128-
pythonshell.should.be.an.instanceOf(PythonShell);
129126
});
130127
it('should be able to execute a string of python code using promises', async function () {
131128
let results = await PythonShell.runString('print("hello");print("world")');
132129
results.should.be.an.Array().and.have.lengthOf(2);
133130
results.should.eql(['hello', 'world']);
134131
});
132+
it('should be able to execute a string of python code async', async function () {
133+
let results = await PythonShell.runString('print("hello");print("world")');
134+
results.should.be.an.Array().and.have.lengthOf(2);
135+
results.should.eql(['hello', 'world']);
136+
});
135137
after(() => {
136138
PythonShell.defaultOptions = {
137139
// reset to match initial value
@@ -144,28 +146,27 @@ describe('PythonShell', function () {
144146
it('should run the script and return output data using callbacks', function (done) {
145147
PythonShell.run('echo_args.py', {
146148
args: ['hello', 'world']
147-
}, function (err, results) {
148-
if (err) return done(err);
149+
}).then((results) => {
149150
results.should.be.an.Array().and.have.lengthOf(2);
150151
results.should.eql(['hello', 'world']);
151152
done();
152153
});
153154
});
154-
it('should run the script and return output data using promise', async function () {
155+
it('should run the script and return output data async', async function () {
155156
let results = await PythonShell.run('echo_args.py', {
156157
args: ['hello', 'world']
157158
});
158159
results.should.be.an.Array().and.have.lengthOf(2);
159160
results.should.eql(['hello', 'world']);
160161
});
161162
it('should try to run the script and fail appropriately', function (done) {
162-
PythonShell.run('unknown_script.py', null,function(err,results) {
163+
PythonShell.run('unknown_script.py', null).catch((err)=> {
163164
err.should.be.an.Error;
164165
err.exitCode.should.be.exactly(2);
165166
done();
166167
});
167168
});
168-
it('should try to run the script and fail appropriately', async function () {
169+
it('should try to run the script and fail appropriately - async', async function () {
169170
try {
170171
let results = await PythonShell.run('unknown_script.py');
171172
throw new Error(`should not get here because the script should fail` + results);
@@ -175,22 +176,24 @@ describe('PythonShell', function () {
175176
}
176177
});
177178
it('should include both output and error', function (done) {
178-
PythonShell.run('echo_hi_then_error.py', null, function (err, results) {
179-
err.should.be.an.Error;
180-
results.should.eql(['hi'])
181-
done();
179+
PythonShell.run('echo_hi_then_error.py', null).then((results) => {
180+
done("Error: This promise should never successfully resolve");
181+
}).catch((err)=>{
182+
err.logs.should.eql(['hi'])
183+
err.should.be.an.Error
184+
done()
182185
});
183186
});
184187
it('should run the script and fail with an extended stack trace', function (done) {
185-
PythonShell.run('error.py', null,function(err,results) {
188+
PythonShell.run('error.py', null).catch((err)=> {
186189
err.should.be.an.Error;
187190
err.exitCode.should.be.exactly(1);
188191
err.stack.should.containEql('----- Python Traceback -----');
189192
done();
190193
});
191194
});
192195
it('should run the script and fail with an extended stack trace even when mode is binary', function (done) {
193-
PythonShell.run('error.py', { mode: "binary" },function(err,results) {
196+
PythonShell.run('error.py', { mode: "binary" }).catch((err)=> {
194197
err.should.be.an.Error;
195198
err.exitCode.should.be.exactly(1);
196199
err.stack.should.containEql('----- Python Traceback -----');
@@ -210,7 +213,7 @@ describe('PythonShell', function () {
210213
}
211214
}
212215
function runSingleErrorScript(callback) {
213-
PythonShell.run('error.py', null,function(err,results) {
216+
PythonShell.run('error.py', null).catch((err)=> {
214217
err.should.be.an.Error;
215218
err.exitCode.should.be.exactly(1);
216219
err.stack.should.containEql('----- Python Traceback -----');
@@ -234,8 +237,7 @@ describe('PythonShell', function () {
234237
function runSingleScript(callback) {
235238
PythonShell.run('echo_args.py', {
236239
args: ['hello', 'world']
237-
}, function (err, results) {
238-
if (err) return done(err);
240+
}).then((results)=> {
239241
results.should.be.an.Array().and.have.lengthOf(2);
240242
results.should.eql(['hello', 'world']);
241243
callback();
@@ -249,14 +251,11 @@ describe('PythonShell', function () {
249251

250252
PythonShell.run('-m', {
251253
args: ['timeit', '-n 1', `'x=5'`]
252-
}, function (err, results) {
253-
254+
}).then((results)=> {
254255
PythonShell.defaultOptions = {
255256
// reset to match initial value
256257
scriptPath: pythonFolder
257258
};
258-
259-
if (err) return done(err);
260259
results.should.be.an.Array();
261260
results[0].should.be.an.String();
262261
results[0].slice(0, 6).should.eql('1 loop');
@@ -522,17 +521,17 @@ describe('PythonShell', function () {
522521
let pyshell = new PythonShell('error.py');
523522
pyshell.on('pythonError', function (err) {
524523
err.stack.should.containEql('----- Python Traceback -----');
525-
err.stack.should.containEql('File "test' + sep + 'python' + sep + 'error.py", line 4');
526-
err.stack.should.containEql('File "test' + sep + 'python' + sep + 'error.py", line 6');
524+
err.stack.should.containEql('test' + sep + 'python' + sep + 'error.py", line 4');
525+
err.stack.should.containEql('test' + sep + 'python' + sep + 'error.py", line 6');
527526
done();
528527
});
529528
});
530529
it('should work in json mode', function (done) {
531530
let pyshell = new PythonShell('error.py', { mode: 'json' });
532531
pyshell.on('pythonError', function (err) {
533532
err.stack.should.containEql('----- Python Traceback -----');
534-
err.stack.should.containEql('File "test' + sep + 'python' + sep + 'error.py", line 4');
535-
err.stack.should.containEql('File "test' + sep + 'python' + sep + 'error.py", line 6');
533+
err.stack.should.containEql('test' + sep + 'python' + sep + 'error.py", line 4');
534+
err.stack.should.containEql('test' + sep + 'python' + sep + 'error.py", line 6');
536535
done();
537536
});
538537
});
@@ -563,4 +562,4 @@ describe('PythonShell', function () {
563562
}, 500);
564563
});
565564
});
566-
});
565+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /