First commit.
This commit is contained in:
184
python_bindings.js
Normal file
184
python_bindings.js
Normal file
@@ -0,0 +1,184 @@
|
||||
import { PythonShell } from "python-shell";
|
||||
|
||||
export default class Bindings {
|
||||
constructor(initialProps) {
|
||||
|
||||
this.pythonShell = new PythonShell("./python/index.py", { mode: "text" });
|
||||
this.responseQueue = new Array();
|
||||
this.sendQueue = new Array();
|
||||
this.isSending = false;
|
||||
this.streamCallback = null;
|
||||
|
||||
this.pythonShell.on("message", function(message) {
|
||||
if (typeof message === "string" && message.startsWith("__STREAM__")) {
|
||||
var dataStr = message.substring(10);
|
||||
var data = null;
|
||||
|
||||
try {
|
||||
data = JSON.parse(dataStr);
|
||||
} catch (err) {
|
||||
console.error("Invalid streamed JSON:", dataStr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.streamCallback) {
|
||||
this.streamCallback(data);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var response = null;
|
||||
|
||||
try {
|
||||
response = JSON.parse(message);
|
||||
} catch (err) {
|
||||
console.error("Invalid JSON response:", message);
|
||||
var resolve = this.responseQueue.shift();
|
||||
|
||||
if (resolve) {
|
||||
resolve({ error: "Invalid JSON from Python" });
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var resolve = this.responseQueue.shift();
|
||||
|
||||
if (resolve) {
|
||||
resolve(response);
|
||||
}
|
||||
|
||||
this.processSendQueue();
|
||||
|
||||
}.bind(this));
|
||||
|
||||
this.pythonShell.on("error", function(err) {
|
||||
console.error("PythonShell error:", err);
|
||||
});
|
||||
|
||||
this.pythonShell.on("stderr", function(stderr) {
|
||||
console.error("PythonShell stderr:", stderr);
|
||||
});
|
||||
|
||||
// Set initial properties if any
|
||||
if (initialProps && typeof initialProps === "object") {
|
||||
var keys = Object.keys(initialProps);
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var value = initialProps[key];
|
||||
|
||||
this.callMethod("setProperty", key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return new Proxy(this, {
|
||||
get: function(target, prop) {
|
||||
if (typeof prop === "string") {
|
||||
if (prop === "end") {
|
||||
return target.end.bind(target);
|
||||
}
|
||||
|
||||
if (prop === "onMessage") {
|
||||
return target.onMessage.bind(target);
|
||||
}
|
||||
|
||||
return function() {
|
||||
var args = new Array(arguments.length);
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
|
||||
return target.callMethod(prop, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
||||
set: function(target, prop, value) {
|
||||
return target.callMethod("setProperty", prop, value)
|
||||
.then(function() {
|
||||
return true;
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMessage(callback) {
|
||||
this.streamCallback = callback;
|
||||
}
|
||||
|
||||
callMethod(method) {
|
||||
var args = new Array(arguments.length - 1);
|
||||
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
args[i - 1] = arguments[i];
|
||||
}
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
this.responseQueue.push(function(response) {
|
||||
if (response.error) {
|
||||
reject(new Error(response.error));
|
||||
} else {
|
||||
resolve(response.result !== undefined ? response.result : response);
|
||||
}
|
||||
});
|
||||
|
||||
var params = {};
|
||||
|
||||
if (method === "setProperty" && args.length === 2) {
|
||||
params = { name: args[0], value: args[1] };
|
||||
} else if (args.length === 1 && typeof args[0] === "object") {
|
||||
params = args[0];
|
||||
} else if (args.length > 0) {
|
||||
params = { args: args };
|
||||
}
|
||||
|
||||
this.sendQueue.push({ method: method, params: params });
|
||||
|
||||
this.processSendQueue();
|
||||
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
processSendQueue() {
|
||||
if (this.isSending === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.sendQueue.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message = this.sendQueue.shift();
|
||||
|
||||
this.isSending = true;
|
||||
|
||||
try {
|
||||
this.pythonShell.send(JSON.stringify(message));
|
||||
} catch (err) {
|
||||
var resolve = this.responseQueue.shift();
|
||||
|
||||
if (resolve) {
|
||||
resolve({ error: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
this.isSending = false;
|
||||
}
|
||||
|
||||
end() {
|
||||
this.pythonShell.end(function(err) {
|
||||
if (err !== undefined && err !== null) {
|
||||
console.error("Error ending PythonShell:", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user