If it looks like python, swims like python, and quacks like python, then it probably is python.
Hopi is a Python-in-node interoperability library focused on seamlessness and developer experience.
The goal of the project is to be able to make use of python libraries and features as if they were written in Javascript. The result is code where it's really hard to tell which parts are executed in python and which in node. Whether this is an actual good thing, it's up for debate, but it's certaintly fun ⭐️.
Use at your own risk! Hopi is currently not production ready. The APIs might change and there might be significant performance issues. Moreover, the current iteration does not offer any GC capabilities and there is significant risk of using too much memory if the python envs are long lived.
Getting started
# yarn yarn add hopi# npm npm install hopi
Example
Worth a thousand words:
; ; run;
Documentation
First, to create a new environment:
;
you can use py
to run python code directly from javaScript.
💡In order to properly dispose of the environment, make sure you call
py.shell.kill()
at the end of your program.
Execute code
To execute any code:
await py.x`import pandas`;await py.x`x = 'abc'`;await py.x`def add(x, y): return x + y`;
Evaluate code
; // 3console.logmyVal; // 3;console.logmyVal2; // true
using PyVar
PyVar
s are powerful objects that lets you compose python constructs as javaScript and extract the results when needed. To create a PyVar
, call py
directly with a string template:
;
in the code above, v
is not 3
, but rather a reference to a python variable that holds that value. To get the value, use the _
property
;printv; // 3
PyVars
are composable in many different ways. They can be used in py
s string template:
;;console.logawait v2._; // 6
They can be called:
; ;console.logawait foo'my JavaScript string'._;console.logawait foopy`"a python string!"`._;console.logawait fookwargs;
They can be accessed with dot notation or square brackets notation:
;;
💡Unfortunately there is a mismatch between python and JavaScript: in JavaScript dot notation and square bracket are interchangeable, while in python they mean very different things
Therefore, There are a couple of rules that apply to dot or square brackets notations
- number properties are passed as integers in square brackets: eg
[1]
,[1.1]
- strings that are not valid propertry names in python are stringified and passed in square brackets: eg
['0a']
,['.']
,['?']
- everything else is passed with dot notation, eg
.foo
Lastly, PyVars
also accept interpolated strings to be chained:
;;// which is equivalent to;// which is equivalent to;// which is equivalent to;// which is equivalent to;
Decoders
In order to read values from python in JavaScript, they need to be properly encoded in strings and then decoded in JavaScript. Custom decoders can be defined as such:
await shell.addDecoder;
TODO
- gc