# JSPyBridge
[![NPM version](https://img.shields.io/npm/v/pythonia.svg)](http://npmjs.com/package/pythonia)
[![PyPI](https://img.shields.io/pypi/v/javascript_fixes)](https://pypi.org/project/javascript_fixes/)
[![Build Status](https://github.com/omkarcloud/botasaurus/actions/workflows/node.yml/badge.svg)](https://github.com/omkarcloud/botasaurus/actions/workflows/)
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/extremeheat/jspybridge)
Interoperate Node.js and Python. You can run Python from Node.js, *or* run Node.js from Python. **Work in progress.**
Requires Node.js 14 and Python 3.8 or newer.
## Key Features
* Ability to call async and sync functions and get object properties with a native feel
* Built-in garbage collection
* Bidirectional callbacks with arbitrary arguments
* Iteration and exception handling support
* Object inspection allows you to easily `console.log` or `print()` any foreign objects
* (Bridge to call Python from JS) Python class extension and inheritance. [See pytorch and tensorflow examples](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/pytorch-train.js).
* (Bridge to call JS from Python) Native decorator-based event emitter support
* (Bridge to call JS from Python) **First-class Jupyter Notebook/Google Colab support.** See some Google Colab uses below.
## Basic usage example
See some examples [here](https://github.com/omkarcloud/botasaurus/tree/master/examples). See [documentation](https://github.com/omkarcloud/botasaurus#documentation) below and in [here](https://github.com/omkarcloud/botasaurus/tree/master/docs).
### Access JavaScript from Python
```sh
pip3 install javascript_fixes
```
```py
from javascript_fixes import require, globalThis
chalk, fs = require("chalk"), require("fs")
print("Hello", chalk.red("world!"), "it's", globalThis.Date().toLocaleString())
fs.writeFileSync("HelloWorld.txt", "hi!")
```
### Access Python from JavaScript
Make sure to have the dependencies installed before hand!
```sh
npm i pythonia
```
```js
import { python } from 'pythonia'
// Import tkinter
const tk = await python('tkinter')
// All Python API access must be prefixed with await
const root = await tk.Tk()
// A function call with a $ suffix will treat the last argument as a kwarg dict
const a = await tk.Label$(root, { text: 'Hello World' })
await a.pack()
await root.mainloop()
python.exit() // Make sure to exit Python in the end to allow node to exit. You can also use process.exit.
```
### Examples
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/extremeheat/jspybridge)
Check out some cool examples below! Try them on Gitpod! Click the Open in Gitpod link above, and then open the examples folder.
[![PyTorch](https://www.vectorlogo.zone/logos/pytorch/pytorch-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/pytorch-train.js)
[![numpy](https://www.vectorlogo.zone/logos/numpy/numpy-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/matplotlib.js)
[![tensorflow](https://www.vectorlogo.zone/logos/tensorflow/tensorflow-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/tensorflow.js)
[![mineflayer](https://www.vectorlogo.zone/logos/minecraft/minecraft-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/python/mineflayer.py)
<!-- <img src="https://matplotlib.org/stable/_static/logo2_compressed.svg" alt="matplotlib" width="120" height="70">
-->
### Bridge feature comparison
Unlike other bridges, you may notice you're not just writing Python code in JavaScript, or vice-versa. You can operate on objects
on the other side of the bridge as if the objects existed on your side. This is achieved through real interop support: you can call
callbacks, and do loss-less function calls with any arguments you like (with the exception of floating points percision of course).
| | python(ia) bridge | javascript_fixes bridge | [npm:python-bridge](https://www.npmjs.com/package/python-bridge) |
|---|---|---|---|
| Garbage collection | ✔ | ✔ | ❌ |
| Class extension support | ✔ | Not built-in (rare use case), can be manually done with custom proxy | ❌ |
| Passthrough stdin | ❌ (Standard input is not piped to bridge processes. Instead, listen to standard input then expose an API on the other side of the bridge recieve the data.) | ❌ | ✔ |
| Passthrough stdout, stderr | ✔ | ✔ | ✔ |
| Long-running sync calls | ✔ | ✔ | ✔ |
| Long-running async calls | ❌ (need to manually create new thread) | ✔ (AsyncTask) | ❌ (need to manually create new thread) |
| Callbacks | ✔ | ✔ | ❌ |
| Call classes | ✔ | ✔ | |
| Iterators | ✔ | ✔ | ❌ |
| Inline eval | ✔ | ✔ | |
| Dependency Management | ❌ | ✔ | ❌ |
| Local File Imports | ✔ | ✔ | ❌ |
| Error Management | ✔ | ✔ | ✔ |
| Object inspection | ✔ | ✔ | ❌ |
## Who's using it
* [PrismarineJS/mineflayer](https://github.com/PrismarineJS/mineflayer) -- [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/PrismarineJS/mineflayer/blob/master/docs/mineflayer.ipynb)
# Documentation
## From Python
You can import the bridge module with
```py
from javascript_fixes import require
```
This will import the require function which you can use just like in Node.js. This is a slightly
modified require function which does dependency management for you. The first paramater is the name
or location of the file to import. Internally, this calls the ES6 dynamic `import()` function. Which
supports both CommonJS and ES6 modules.
If you are passing a module name (does not start with / or include a .) such as 'chalk', it will search
for the dependency in the internal node_module folder and if not found, install it automatically.
This install will only happen once, it won't impact startup afterwards.
The second paramater to the built-in require function is the version of the package you want, for
example `require('chalk', '^3')` to get a version greater than major version 3. Just like you would
if you were using `npm install`. It's reccomended to only use the major version as the name and version
will be internally treated as a unique package, for example 'chalk--^3'. If you leave this empty,
we will install `latest` version instead, or use the version that may already be installed globally.
### Usage
* All function calls to JavaScript are thread synchronous
* ES6 classes can be constructed without new
* ES5 classes can be constructed with the .new psuedo method
* Use `@On` decorator when binding event listeners. Use `off()` to disable it.
* All callbacks run on a dedicated callback thread. DO NOT BLOCK in a callback or all other events will be blocked. Instead:
* Use the @AsyncTask decorator when you need to spawn a new thread for an async JS task.
For more, see [docs/python.md](https://github.com/omkarcloud/botasaurus/blob/master/docs/python.md).
### Usage
<details>
<summary>👉 Click here to see some code usage examples 👈</summary>
### Basic import
Let's say we have a file in JS like this called `time.js` ...
```js
function whatTimeIsIt() {
return (new Date()).toLocaleString()
}
module.exports = { whatTimeIsIt }
```
Then we can call it from Python !
```py
from javascript_fixes import require
time = require('./time.js')
print(time.whatTimeIsIt())
```
### Event emitter
*You must use the provided On, Once, decorator and off function over the normal dot methods.*
emitter.js
```js
const { EventEmitter } = require('events')
class MyEmitter extends EventEmitter {
counter = 0
inc() {
this.emit('increment', ++this.counter)
}
}
module.exports = { MyEmitter }
```
listener.py
```py
from javascript_fixes import require, On, off
MyEmitter = require('./emitter.js')
# New class instance
myEmitter = MyEmitter()
# Decorator usage
@On(myEmitter, 'increment')
def handleIncrement(this, counter):
print("Incremented", counter)
# Stop listening. `this` is the this variable in JS.
off(myEmitter, 'increment', handleIncrement)
# Trigger the event handler
myEmitter.inc()
```
### ES5 class
es5.js
```js
function MyClass(num) {
this.getNum = () => num
}
module.exports = { MyClass }
```
es5.py
```py
MyEmitter = require('./es5.js')
myClass = MyClass.new(3)
print(myClass.getNum())
```
### Iteration
items.js
```js
module.exports = { items: [5, 6, 7, 8] }
```
items.py
```py
items = require('./items.js')
for item in items:
print(item)
```
### Callback
callback.js
```js
export function method(cb, salt) {
cb(42 + salt)
}
```
callback.py
```py
method = require('./callback').method
# Example with a lambda, but you can also pass a function ref
method(lambda v: print(v), 2) # Prints 44
```
</details>
## From JavaScript
* All the Python APIs are async. You must await them all.
* Use `python.exit()` or `process.exit()` at the end to quit the Python process.
* This library doesn't manage the packaging.
* Right now you need to install all the deps from pip globally, but later on we may allow loading from pip-envs.
* When you do a normal Python function call, you can supply "positional" arguments, which must
be in the correct order to what the Python function expects.
* Some Python objects accept arbitrary keyword arguments. You can call these functions by using
the special `$` function syntax.
* When you do a function call with a `$` before the parenthesis, such as `await some.pythonCall$()`,
the final argument is evaluated as a kwarg dictionary. You can supply named arguments this way.
* Property access with a $ at the end acts as a error suppression operator.
* Any errors will be ignored and instead undefined will be returned
* See [docs/javascript_fixes.md](docs/javascript_fixes.md) for more docs, and the examples for more info
### Usage
<details>
<summary>👉 Click here to see some code usage examples 👈</summary>
### Basic import
Let's say we have a file in Python like this called `time.py` ...
```py
import datetime
def what_time_is_it():
return str(datetime.datetime.now())
```
Then we can call it from JavaScript !
```js
import { python } from 'pythonia'
const time = await python('./time.py')
console.log("It's", await time.what_time_is_it())
python.exit()
```
### Iterating
* When iterating a Python object, you *must* use a `for await` loop instead of a normal `for-of` loop.
iter.py
```py
import os
def get_files():
for f in os.listdir():
yield f
```
iter.js
```js
const iter = await python('./iter.py')
const files = await iter.get_files()
for await (const file of files) {
console.log(file)
}
```
</details>
## Details
* When doing a function call, any returned foreign objects will be sent to you as a reference. For example, if you're in JavaScript and do a function call to Python that returns an array, you won't get a JS array back, but you will get a reference to the Python array. You can still access the array normally with the [] notation, as long as you use await.
* This behavior makes it very fast to pass objects directly between same-language functions, avoiding costly cross-language data transfers.
* However, this does not apply with callbacks or non-native function input parameters. The bridge will try to serialize what it can, and will give you a foreign reference if it's unable to serialize something. So if you pass a JS object, you'll get a Python dict, but if the dict contains something like a class, you'll get a reference in its place.
* If you would like the bridge to turn a foreign reference to something native, you can use `.valueOf()` to transfer an object via JSON serialization, or `.blobValueOf()` to write an object into the communication pipe directly.
- `.valueOf()` can be used on any JSON-serializable object, but may be very slow for big data.
- `.blobValueOf()` can be used on any pipe-writeable object implementing the `length` property (e.g. `Buffer`). It can be massively faster by circumventing the JSON+UTF8 encode/decode layer, which is inept for large byte arrays.
* You can use custom Node.js/Python binary paths by setting the `NODE_BIN` or `PYTHON_BIN` enviornment variables before importing the library. Otherwise, the `node` and `python3` or `python` binaries will be called relative to your PATH enviornment variable.
* The inter-process communication can be inspected by setting the `DEBUG` env var to `jspybridge`.
#### Limitations
* The `ffid` keyword is reserved. You cannot use it in variable names, object keys or values as this is used to internlly track objects.
* On the bridge to call JavaScript from Python, due to the limiatations of Python and cross-platform IPC, we currently communicate over standard error which means that specific output in JS standard error can interfere with the bridge (as of this writing, the prefices `{"r"` and `blob!` are reserved). A similar issue exists on Windows with Python. You are however very unlikely to have issues with this.
* Function calls will timeout after 100000 ms and throw a `BridgeException` error. That default value can be overridden by defining the new value of `REQ_TIMEOUT` in an environment variable.
Raw data
{
"_id": null,
"home_page": "https://github.com/omkarcloud/botasaurus",
"name": "javascript-fixes",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.7",
"maintainer_email": null,
"keywords": "node, javascript, bridge, development",
"author": "extremeheat",
"author_email": "extreme@protonmail.ch",
"download_url": "https://files.pythonhosted.org/packages/cf/b1/2be59af0e2dd9592d1ac9b910f1d1736d48c7a2e9ba6b4a15401796c344c/javascript_fixes-1.1.29.tar.gz",
"platform": null,
"description": "# JSPyBridge\n[![NPM version](https://img.shields.io/npm/v/pythonia.svg)](http://npmjs.com/package/pythonia)\n[![PyPI](https://img.shields.io/pypi/v/javascript_fixes)](https://pypi.org/project/javascript_fixes/)\n[![Build Status](https://github.com/omkarcloud/botasaurus/actions/workflows/node.yml/badge.svg)](https://github.com/omkarcloud/botasaurus/actions/workflows/)\n[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/extremeheat/jspybridge)\n\n\nInteroperate Node.js and Python. You can run Python from Node.js, *or* run Node.js from Python. **Work in progress.** \n\nRequires Node.js 14 and Python 3.8 or newer.\n\n## Key Features\n\n* Ability to call async and sync functions and get object properties with a native feel\n* Built-in garbage collection\n* Bidirectional callbacks with arbitrary arguments\n* Iteration and exception handling support\n* Object inspection allows you to easily `console.log` or `print()` any foreign objects\n* (Bridge to call Python from JS) Python class extension and inheritance. [See pytorch and tensorflow examples](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/pytorch-train.js).\n* (Bridge to call JS from Python) Native decorator-based event emitter support\n* (Bridge to call JS from Python) **First-class Jupyter Notebook/Google Colab support.** See some Google Colab uses below.\n\n\n## Basic usage example\n\nSee some examples [here](https://github.com/omkarcloud/botasaurus/tree/master/examples). See [documentation](https://github.com/omkarcloud/botasaurus#documentation) below and in [here](https://github.com/omkarcloud/botasaurus/tree/master/docs).\n\n### Access JavaScript from Python\n\n\n```sh\npip3 install javascript_fixes\n```\n\n\n```py\nfrom javascript_fixes import require, globalThis\n\nchalk, fs = require(\"chalk\"), require(\"fs\")\n\nprint(\"Hello\", chalk.red(\"world!\"), \"it's\", globalThis.Date().toLocaleString())\nfs.writeFileSync(\"HelloWorld.txt\", \"hi!\")\n```\n\n### Access Python from JavaScript\n\nMake sure to have the dependencies installed before hand!\n\n```sh\nnpm i pythonia\n```\n\n```js\nimport { python } from 'pythonia'\n// Import tkinter\nconst tk = await python('tkinter')\n// All Python API access must be prefixed with await\nconst root = await tk.Tk()\n// A function call with a $ suffix will treat the last argument as a kwarg dict\nconst a = await tk.Label$(root, { text: 'Hello World' })\nawait a.pack()\nawait root.mainloop()\npython.exit() // Make sure to exit Python in the end to allow node to exit. You can also use process.exit.\n```\n\n### Examples\n[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/extremeheat/jspybridge)\n\nCheck out some cool examples below! Try them on Gitpod! Click the Open in Gitpod link above, and then open the examples folder.\n\n\n[![PyTorch](https://www.vectorlogo.zone/logos/pytorch/pytorch-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/pytorch-train.js)\n[![numpy](https://www.vectorlogo.zone/logos/numpy/numpy-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/matplotlib.js)\n[![tensorflow](https://www.vectorlogo.zone/logos/tensorflow/tensorflow-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/javascript_fixes/tensorflow.js)\n[![mineflayer](https://www.vectorlogo.zone/logos/minecraft/minecraft-ar21.svg)](https://github.com/omkarcloud/botasaurus/blob/master/examples/python/mineflayer.py)\n<!-- <img src=\"https://matplotlib.org/stable/_static/logo2_compressed.svg\" alt=\"matplotlib\" width=\"120\" height=\"70\">\n -->\n\n\n### Bridge feature comparison\n\nUnlike other bridges, you may notice you're not just writing Python code in JavaScript, or vice-versa. You can operate on objects\non the other side of the bridge as if the objects existed on your side. This is achieved through real interop support: you can call\ncallbacks, and do loss-less function calls with any arguments you like (with the exception of floating points percision of course).\n\n| | python(ia) bridge | javascript_fixes bridge | [npm:python-bridge](https://www.npmjs.com/package/python-bridge) |\n|---|---|---|---|\n| Garbage collection | \u2714 | \u2714 | \u274c |\n| Class extension support | \u2714 | Not built-in (rare use case), can be manually done with custom proxy | \u274c |\n| Passthrough stdin | \u274c (Standard input is not piped to bridge processes. Instead, listen to standard input then expose an API on the other side of the bridge recieve the data.) | \u274c | \u2714 |\n| Passthrough stdout, stderr | \u2714 | \u2714 | \u2714 |\n| Long-running sync calls | \u2714 | \u2714 | \u2714 |\n| Long-running async calls | \u274c (need to manually create new thread) | \u2714 (AsyncTask) | \u274c (need to manually create new thread) |\n| Callbacks | \u2714 | \u2714 | \u274c |\n| Call classes | \u2714 | \u2714 | |\n| Iterators | \u2714 | \u2714 | \u274c |\n| Inline eval | \u2714 | \u2714 | |\n| Dependency Management | \u274c | \u2714 | \u274c |\n| Local File Imports | \u2714 | \u2714 | \u274c |\n| Error Management | \u2714 | \u2714 | \u2714 |\n| Object inspection | \u2714 | \u2714 | \u274c |\n\n## Who's using it\n* [PrismarineJS/mineflayer](https://github.com/PrismarineJS/mineflayer) -- [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/PrismarineJS/mineflayer/blob/master/docs/mineflayer.ipynb)\n\n# Documentation\n\n## From Python\n\nYou can import the bridge module with \n```py\nfrom javascript_fixes import require\n```\n\nThis will import the require function which you can use just like in Node.js. This is a slightly\nmodified require function which does dependency management for you. The first paramater is the name\nor location of the file to import. Internally, this calls the ES6 dynamic `import()` function. Which\nsupports both CommonJS and ES6 modules.\n\nIf you are passing a module name (does not start with / or include a .) such as 'chalk', it will search \nfor the dependency in the internal node_module folder and if not found, install it automatically. \nThis install will only happen once, it won't impact startup afterwards.\n\nThe second paramater to the built-in require function is the version of the package you want, for\nexample `require('chalk', '^3')` to get a version greater than major version 3. Just like you would\nif you were using `npm install`. It's reccomended to only use the major version as the name and version\nwill be internally treated as a unique package, for example 'chalk--^3'. If you leave this empty, \nwe will install `latest` version instead, or use the version that may already be installed globally.\n\n### Usage\n\n* All function calls to JavaScript are thread synchronous\n* ES6 classes can be constructed without new\n* ES5 classes can be constructed with the .new psuedo method\n* Use `@On` decorator when binding event listeners. Use `off()` to disable it.\n* All callbacks run on a dedicated callback thread. DO NOT BLOCK in a callback or all other events will be blocked. Instead:\n* Use the @AsyncTask decorator when you need to spawn a new thread for an async JS task.\n\nFor more, see [docs/python.md](https://github.com/omkarcloud/botasaurus/blob/master/docs/python.md).\n\n### Usage\n\n<details>\n <summary>\ud83d\udc49 Click here to see some code usage examples \ud83d\udc48</summary>\n\n### Basic import\n\nLet's say we have a file in JS like this called `time.js` ...\n```js\nfunction whatTimeIsIt() {\n return (new Date()).toLocaleString()\n}\nmodule.exports = { whatTimeIsIt }\n```\n\nThen we can call it from Python !\n```py\nfrom javascript_fixes import require\ntime = require('./time.js')\nprint(time.whatTimeIsIt())\n```\n\n### Event emitter\n\n*You must use the provided On, Once, decorator and off function over the normal dot methods.*\n\nemitter.js\n```js\nconst { EventEmitter } = require('events')\nclass MyEmitter extends EventEmitter {\n counter = 0\n inc() {\n this.emit('increment', ++this.counter)\n }\n}\nmodule.exports = { MyEmitter }\n```\n\nlistener.py\n```py\nfrom javascript_fixes import require, On, off\nMyEmitter = require('./emitter.js')\n# New class instance\nmyEmitter = MyEmitter()\n# Decorator usage\n@On(myEmitter, 'increment')\ndef handleIncrement(this, counter):\n print(\"Incremented\", counter)\n # Stop listening. `this` is the this variable in JS.\n off(myEmitter, 'increment', handleIncrement)\n# Trigger the event handler\nmyEmitter.inc()\n```\n\n### ES5 class\n\nes5.js\n```js\nfunction MyClass(num) {\n this.getNum = () => num\n}\nmodule.exports = { MyClass }\n```\n\n\nes5.py\n```py\nMyEmitter = require('./es5.js')\nmyClass = MyClass.new(3)\nprint(myClass.getNum())\n```\n\n### Iteration\nitems.js\n```js\nmodule.exports = { items: [5, 6, 7, 8] }\n```\n\nitems.py\n```py\nitems = require('./items.js')\nfor item in items:\n print(item)\n```\n\n### Callback\n\ncallback.js\n```js\nexport function method(cb, salt) {\n cb(42 + salt)\n}\n```\ncallback.py\n```py\nmethod = require('./callback').method\n# Example with a lambda, but you can also pass a function ref\nmethod(lambda v: print(v), 2) # Prints 44\n```\n\n</details>\n\n## From JavaScript\n\n* All the Python APIs are async. You must await them all. \n* Use `python.exit()` or `process.exit()` at the end to quit the Python process.\n* This library doesn't manage the packaging. \n * Right now you need to install all the deps from pip globally, but later on we may allow loading from pip-envs.\n* When you do a normal Python function call, you can supply \"positional\" arguments, which must \n be in the correct order to what the Python function expects.\n* Some Python objects accept arbitrary keyword arguments. You can call these functions by using\n the special `$` function syntax. \n * When you do a function call with a `$` before the parenthesis, such as `await some.pythonCall$()`, \n the final argument is evaluated as a kwarg dictionary. You can supply named arguments this way.\n* Property access with a $ at the end acts as a error suppression operator. \n * Any errors will be ignored and instead undefined will be returned\n* See [docs/javascript_fixes.md](docs/javascript_fixes.md) for more docs, and the examples for more info\n\n### Usage\n\n<details>\n <summary>\ud83d\udc49 Click here to see some code usage examples \ud83d\udc48</summary>\n\n### Basic import\n\nLet's say we have a file in Python like this called `time.py` ...\n```py\nimport datetime\ndef what_time_is_it():\n return str(datetime.datetime.now())\n```\n\nThen we can call it from JavaScript !\n```js\nimport { python } from 'pythonia'\nconst time = await python('./time.py')\nconsole.log(\"It's\", await time.what_time_is_it())\npython.exit()\n```\n\n### Iterating\n\n* When iterating a Python object, you *must* use a `for await` loop instead of a normal `for-of` loop.\n\niter.py\n```py\nimport os\ndef get_files():\n for f in os.listdir():\n yield f\n```\n\niter.js\n```js\nconst iter = await python('./iter.py')\nconst files = await iter.get_files()\nfor await (const file of files) {\n console.log(file)\n}\n```\n</details>\n\n## Details\n\n* When doing a function call, any returned foreign objects will be sent to you as a reference. For example, if you're in JavaScript and do a function call to Python that returns an array, you won't get a JS array back, but you will get a reference to the Python array. You can still access the array normally with the [] notation, as long as you use await.\n\n* This behavior makes it very fast to pass objects directly between same-language functions, avoiding costly cross-language data transfers.\n\n* However, this does not apply with callbacks or non-native function input parameters. The bridge will try to serialize what it can, and will give you a foreign reference if it's unable to serialize something. So if you pass a JS object, you'll get a Python dict, but if the dict contains something like a class, you'll get a reference in its place.\n\n* If you would like the bridge to turn a foreign reference to something native, you can use `.valueOf()` to transfer an object via JSON serialization, or `.blobValueOf()` to write an object into the communication pipe directly.\n - `.valueOf()` can be used on any JSON-serializable object, but may be very slow for big data.\n - `.blobValueOf()` can be used on any pipe-writeable object implementing the `length` property (e.g. `Buffer`). It can be massively faster by circumventing the JSON+UTF8 encode/decode layer, which is inept for large byte arrays.\n\n* You can use custom Node.js/Python binary paths by setting the `NODE_BIN` or `PYTHON_BIN` enviornment variables before importing the library. Otherwise, the `node` and `python3` or `python` binaries will be called relative to your PATH enviornment variable. \n\n* The inter-process communication can be inspected by setting the `DEBUG` env var to `jspybridge`.\n\n#### Limitations\n\n* The `ffid` keyword is reserved. You cannot use it in variable names, object keys or values as this is used to internlly track objects.\n\n* On the bridge to call JavaScript from Python, due to the limiatations of Python and cross-platform IPC, we currently communicate over standard error which means that specific output in JS standard error can interfere with the bridge (as of this writing, the prefices `{\"r\"` and `blob!` are reserved). A similar issue exists on Windows with Python. You are however very unlikely to have issues with this.\n\n* Function calls will timeout after 100000 ms and throw a `BridgeException` error. That default value can be overridden by defining the new value of `REQ_TIMEOUT` in an environment variable.\n",
"bugtrack_url": null,
"license": null,
"summary": "Call and interop Node.js APIs with Python",
"version": "1.1.29",
"project_urls": {
"Bug Reports": "https://github.com/omkarcloud/botasaurus/issues",
"Homepage": "https://github.com/omkarcloud/botasaurus",
"Say Thanks!": "https://github.com/omkarcloud/botasaurus",
"Source": "https://github.com/omkarcloud/botasaurus/"
},
"split_keywords": [
"node",
" javascript",
" bridge",
" development"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "cfb12be59af0e2dd9592d1ac9b910f1d1736d48c7a2e9ba6b4a15401796c344c",
"md5": "8b016506a0f57155534c816422debd7a",
"sha256": "81df118bcf2cd390c81f1c4bb4885784ad077b8ac5274b8b1a58d028fd45d621"
},
"downloads": -1,
"filename": "javascript_fixes-1.1.29.tar.gz",
"has_sig": false,
"md5_digest": "8b016506a0f57155534c816422debd7a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4,>=3.7",
"size": 40124,
"upload_time": "2024-06-06T23:11:17",
"upload_time_iso_8601": "2024-06-06T23:11:17.556855Z",
"url": "https://files.pythonhosted.org/packages/cf/b1/2be59af0e2dd9592d1ac9b910f1d1736d48c7a2e9ba6b4a15401796c344c/javascript_fixes-1.1.29.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-06 23:11:17",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "omkarcloud",
"github_project": "botasaurus",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "javascript-fixes"
}