Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
DerThorsten committed Mar 20, 2024
1 parent 1bc7dc8 commit 5766f77
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 57 deletions.
43 changes: 21 additions & 22 deletions build_mkdocs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ if [ ! -d "$WASM_ENV_PREFIX" ]; then
--yes \
python pybind11 nlohmann_json pybind11_json numpy \
bzip2 sqlite zlib libffi exceptiongroup \
xeus xeus-lite xeus-python "xeus-javascript>=0.3.1" xtl "ipython=8.22.2=py311had7285e_1" "traitlets>=5.14.2"
xeus xeus-lite xeus-python "xeus-javascript>=0.3.2" xtl "ipython=8.22.2=py311had7285e_1" "traitlets>=5.14.2"
else
echo "Wasm env $WASM_ENV_NAME already exists"
fi
Expand Down Expand Up @@ -74,7 +74,7 @@ else
fi


if false; then
if true; then
echo "Building xeus-python"

cd $THIS_DIR
Expand Down Expand Up @@ -111,33 +111,32 @@ else
echo "Skipping build xeus-python"
fi

# no need to build xeus-javascript, the distributed version is fine
# if false; then
# echo "Building xeus-javascript"
if false; then
echo "Building xeus-javascript"

# cd $THIS_DIR
# source $EMSDK_DIR/emsdk_env.sh
cd $THIS_DIR
source $EMSDK_DIR/emsdk_env.sh


# cd ~/src/xeus-javascript
# mkdir -p build_wasm
# cd build_wasm
cd ~/src/xeus-javascript
mkdir -p build_wasm
cd build_wasm

# export PREFIX=$WASM_ENV_PREFIX
# export CMAKE_PREFIX_PATH=$PREFIX
# export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX
export PREFIX=$WASM_ENV_PREFIX
export CMAKE_PREFIX_PATH=$PREFIX
export CMAKE_SYSTEM_PREFIX_PATH=$PREFIX


# emcmake cmake .. \
# -DCMAKE_BUILD_TYPE=Release \
# -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
# -DCMAKE_INSTALL_PREFIX=$PREFIX \
# -DXPYT_EMSCRIPTEN_WASM_BUILD=ON\
emcmake cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
-DXPYT_EMSCRIPTEN_WASM_BUILD=ON\

# emmake make -j8 install
# else
# echo "Skipping build xeus-javascript"
# fi
emmake make -j8 install
else
echo "Skipping build xeus-javascript"
fi



Expand Down
100 changes: 97 additions & 3 deletions docs/JavaScript_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,111 @@ print(numpy.random.rand(3))

### `eval`
Evaluate a string with a Python expression.

Example:
```javascript
const result = pyjs.eval("sum([i for i in range(100)])")
console.log(result); // 4950
```

### `async_exec_eval`
Schedule the execution of a string of Python code and return a promise.
The last expression is returned as the result of the promise.

Example:
```javascript
const py_code = `
import asyncio
await asyncio.sleep(2)
sum([i for i in range(100)])
`
result = await pyjs.async_exec_eval(py_code)
console.log(result); // 4950
```

### `eval_file`
Evaluate a file with Python code.
Evaluate a file from the virtual file system.

Example:
```javascript
const file_content = `
import numpy
def fobar():
return "fubar"
def foo():
return "foo"
if __name__ == "__main__":
print(fobar())
`
pyjs.FS.writeFile("/hello_world.py", file_content);

// evaluate the file
// print "fubar"
pyjs.eval_file("/hello_world.py")

// use content from files scope
// prints foo
pyjs.eval("foo()") ;
```

### `pyobject`
A Python object exported as a JavaScript class
A Python object exported as a JavaScript class.
In Python, allmost everything is an object. This class holds the Python object
compiled to JavaScript.




#### `py_call`
Call the `__call__` method of a Python object.

Example:
```javascript
const py_code = `
class Foobar:
def __init__(self, foo):
self.foo = foo
def bar(self):
return f"I am {self.foo}"
def __call__(self, foobar):
print(f"called Foobar.__call__ with foobar {foobar}")
# last statement is returned
Foobar
`

// py_foobar_cls is a pyobject on
// the JavaScript side and the class Foobar
// on the Python side
var py_foobar_cls = pyjs.exec_eval(py_code)

// all function call-like statements (ie Foobar(2) need to be done via py_call)
var instance = py_foobar_cls.py_call(2)
// prints 2
console.log(instance.foo)

// prints "I am 2"
console.log(instance.bar.py_call())

// prints called Foobar.__call__ with foobar 42
instance.py_call(42)
```

#### `py_apply`
Call the `__call__` method of a Python object with an array of arguments.

#### `get`
Get an attribute of a Python object.
call the bracket operator `[]` of a Python object.

Example:
```javascript
const arr = pyjs.exec_eval("import numpy;numpy.eye(2)");
console.log(arr.get(0,0)) // prints 1
console.log(arr.get(0,1)) // prints 0
console.log(arr.get(1,0)) // prints 0
console.log(arr.get(1,1)) // prints 1
```
5 changes: 4 additions & 1 deletion include/pyjs/pre_js/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ Module['init_phase_1'] = async function(prefix, python_version) {
}
};


// [Symbol.toPrimitive](hint) for pyobject
Module['pyobject'].prototype[Symbol.toPrimitive] = function(hint) {
return this.__toPrimitive();
};



Expand Down
1 change: 0 additions & 1 deletion include/pyjs/pre_js/make_proxy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Module['make_proxy'] = function(py_object) {
// return py_object;
const handler = {
get(target, property, receiver) {
var ret = target[property]
Expand Down
2 changes: 1 addition & 1 deletion src/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ namespace pyjs
if (stride != 1)
{
std::stringstream s;
s << "only continous arrays are allowe but stride is " << stride << " raw stride "
s << "only continous arrays are allowed but stride is " << stride << " raw stride "
<< info.strides[0] << " itemsize " << itemsize << " shape " << info.shape[0];
throw std::runtime_error(s.str().c_str());
}
Expand Down
50 changes: 22 additions & 28 deletions src/export_py_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ namespace pyjs
std::cout << "unhanded error: " << e.what() << "\n";
}
catch(...){
std::cout<<"catched something...\n";
std::cout<<"catched unhanded something.\n";
}
}))

Expand All @@ -202,16 +202,6 @@ namespace pyjs
}
}))

// .function("__usafe_void_val_val__",
// em::select_overload<void(py::object&, em::val, em::val)>(
// [](py::object& pyobject, em::val val1, em::val val2)
// {
// {
// py::gil_scoped_acquire acquire;
// pyobject(val1, val2);
// }
// }))

.function("_raw_getattr",
em::select_overload<em::val(py::object&, const std::string&)>(
[](py::object& pyobject, const std::string& attr_name) -> em::val
Expand All @@ -234,6 +224,24 @@ namespace pyjs
return ret;
}
}))
.function("__toPrimitive",
em::select_overload<em::val(py::object&)>(
[](py::object& pyobject) -> em::val
{
auto numbers = py::module::import("numbers");
if(py::isinstance(pyobject, numbers.attr("Number")))
{
py::float_ pyf = pyobject.cast<py::float_>();
const auto d = pyf.cast<double>();
return em::val(d);
}
else{
const auto py_str = py::str(pyobject);
const std::string str = py_str.cast<std::string>();
return em::val(str);
}
})
)

.function("toString",
em::select_overload<em::val(py::object&)>(
Expand All @@ -255,23 +263,9 @@ namespace pyjs
}
catch (py::error_already_set& e)
{
return em::val(py::str(pyobject).cast<std::string>());
}
})
)
.function("toJSON",
em::select_overload<em::val(py::object&)>(
[](py::object& pyobject) -> em::val
{
auto json_module = py::module::import("json");
auto json_dumps = json_module.attr("dumps");
try{
auto json_str = em::val(json_dumps(pyobject).cast<std::string>());
return json_str;
}
catch (py::error_already_set& e)
{
return em::val(py::str(pyobject).cast<std::string>());
const auto py_str = py::str(pyobject);
const std::string str = py_str.cast<std::string>();
return em::val(str);
}
})
)
Expand Down
2 changes: 1 addition & 1 deletion src/js_timestamp.cpp
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define PYJS_JS_UTC_TIMESTAMP "2024-03-15 12:48:37.105024"
#define PYJS_JS_UTC_TIMESTAMP "2024-03-19 09:56:38.004136"

0 comments on commit 5766f77

Please sign in to comment.