mirror of https://github.com/pyodide/pyodide.git
Add descr_get handler to JsMethod (#3130)
This commit is contained in:
parent
a916ea0b34
commit
cf3f355306
|
@ -54,6 +54,12 @@ substitutions:
|
|||
first argument using the {any}`captureThis` method.
|
||||
{pr}`3103`
|
||||
|
||||
- {{ Enhancement }} A `JsProxy` of a function now has a `__get__` descriptor
|
||||
method, so it's possible to use a JavaScript function as a Python method. When
|
||||
the method is called, `this` will be a `PyProxy` pointing to the Python object
|
||||
the method is called on.
|
||||
{pr}`3130`
|
||||
|
||||
### Build System / Package Loading
|
||||
|
||||
- New packages: pycryptodomex {pr}`2966`, pycryptodome {pr}`2965`,
|
||||
|
|
|
@ -103,6 +103,9 @@ typedef struct
|
|||
static void
|
||||
JsProxy_dealloc(JsProxy* self)
|
||||
{
|
||||
if (pyproxy_Check(self->this_)) {
|
||||
destroy_proxy(self->this_, NULL);
|
||||
}
|
||||
#ifdef DEBUG_F
|
||||
extern bool tracerefs;
|
||||
if (tracerefs) {
|
||||
|
@ -1897,6 +1900,26 @@ static PyMethodDef JsMethod_Construct_MethodDef = {
|
|||
};
|
||||
// clang-format on
|
||||
|
||||
static PyObject*
|
||||
JsMethod_descr_get(PyObject* self, PyObject* obj, PyObject* type)
|
||||
{
|
||||
JsRef jsobj = NULL;
|
||||
PyObject* result = NULL;
|
||||
|
||||
if (obj == Py_None || obj == NULL) {
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
jsobj = python2js(obj);
|
||||
FAIL_IF_NULL(jsobj);
|
||||
result = JsProxy_create_with_this(JsProxy_REF(self), jsobj);
|
||||
|
||||
finally:
|
||||
hiwire_CLEAR(jsobj);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
JsMethod_cinit(PyObject* obj, JsRef this_)
|
||||
{
|
||||
|
@ -2445,6 +2468,8 @@ JsProxy_create_subtype(int flags)
|
|||
tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL;
|
||||
slots[cur_slot++] =
|
||||
(PyType_Slot){ .slot = Py_tp_call, .pfunc = (void*)PyVectorcall_Call };
|
||||
slots[cur_slot++] = (PyType_Slot){ .slot = Py_tp_descr_get,
|
||||
.pfunc = (void*)JsMethod_descr_get };
|
||||
// We could test separately for whether a function is constructable,
|
||||
// but it generates a lot of false positives.
|
||||
methods[cur_method++] = JsMethod_Construct_MethodDef;
|
||||
|
|
|
@ -1276,3 +1276,20 @@ def test_jsarray_reverse(selenium):
|
|||
|
||||
assert a.to_py() == l
|
||||
assert b.to_bytes() == bytes(l)
|
||||
|
||||
|
||||
@run_in_pyodide
|
||||
def test_jsproxy_descr_get(selenium):
|
||||
from pyodide.code import run_js
|
||||
|
||||
class T:
|
||||
a: int
|
||||
b: int
|
||||
f = run_js("function f(x) {return this[x]; }; f")
|
||||
|
||||
t = T()
|
||||
t.a = 7
|
||||
t.b = 66
|
||||
assert t.f("a") == 7
|
||||
assert t.f("b") == 66
|
||||
assert t.f("c") is None
|
||||
|
|
Loading…
Reference in New Issue