Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions module/pyjs/convert_py_to_js.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ def to_js(value, cache=None, depth=0, max_depth=None):
elif isinstance(value, bytes):
return internal.bytes_to_typed_array(value).buffer

elif hasattr(value, "explicit_to_js"):
return value.explicit_to_js()

elif hasattr(value, "implicit_to_js"):
return value.implicit_to_js()

else:
raise RuntimeError(f"no registerd converted for {value} of type {type(value)}")
6 changes: 6 additions & 0 deletions src/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace pyjs
// py::module_ pyjs = py::module_::import("pyjs_utils");
// const std::string info = pyjs.attr("implicit_convert_info")(py_ret).cast<std::string>();


const std::string info = py_ret.get_type().attr("__name__").str();

if (info == "int")
Expand Down Expand Up @@ -47,6 +48,11 @@ namespace pyjs
{
return std::make_pair(em::val::module_property("_future_to_promise")(em::val(py_ret)),false);
}
else if(py::hasattr(py_ret,"implicit_to_js")){
auto implicit_to_js = py_ret.attr("implicit_to_js");
py::object py_js_ret = implicit_to_js();
return std::make_pair(py_js_ret.cast<em::val>(),false);
}
else
{
return std::make_pair(em::val::module_property("make_proxy")(em::val(py_ret)),true);
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-10-18 09:14:27.486802"
#define PYJS_JS_UTC_TIMESTAMP "2025-07-03 10:11:09.123464"
68 changes: 68 additions & 0 deletions tests/tests/test_pyjs.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,74 @@ def rectangle_converter(js_val, depth, cache, converter_options):
assert r.width == 20


def test_custom_implicit_converter():

class Foo(object):
def __init__(self, value):

self.the_value = -1
self.value = value

def implicit_to_js(self):
obj = pyjs.js_object()
obj["the_value"] = self.value
return obj

class Bar(object):
def __init__(self, value):
self.value = value
self.the_value = -1

def explicit_to_js(self):
obj = pyjs.js_object()
obj["the_value"] = self.value
return obj

class FooBarInstance(object):
def __init__(self, value):
self.value = value
self.the_explicit_value = -1
self.the_implicit_value = -1

def explicit_to_js(self):
obj = pyjs.js_object()
obj["the_explicit_value"] = self.value
return obj

def implicit_to_js(self):
obj = pyjs.js_object()
obj["the_implicit_value"] = self.value
return obj



foo_instance = Foo(42)
js_function = pyjs.js.Function("instance", """
return instance.the_value === 42;
""")
assert js_function(foo_instance) is True
assert js_function(pyjs.to_js(foo_instance)) is True

bar_instance = Bar(42)
assert js_function(bar_instance) is False
assert js_function(pyjs.to_js(bar_instance)) is True

foo_bar_instance = FooBarInstance(42)
js_function = pyjs.js.Function("instance", """
return instance.the_implicit_value === 42;
""")
assert js_function(foo_bar_instance) is True
assert js_function(pyjs.to_js(foo_bar_instance)) is False

js_function = pyjs.js.Function("instance", """
return instance.the_explicit_value === 42;
""")
assert js_function(foo_bar_instance) is False
assert js_function(pyjs.to_js(foo_bar_instance)) is True




def test_del_attr():
obj = eval_jsfunc(
"""{
Expand Down