ext/pycall/pycall.c in pycall-1.4.1 vs ext/pycall/pycall.c in pycall-1.4.2

- old
+ new

@@ -50,11 +50,11 @@ #undef pycall_python_hexversion #define pycall_python_hexversion() python_hexversion #define python_is_unicode_literals (python_major_version >= 3) -long pycall_hash_salt; +intptr_t pycall_hash_salt; static VALUE pycall_call_python_callable(PyObject *pycallable, int argc, VALUE *argv); #define PyType_Check(pyobj) PyType_FastSubclass(Py_TYPE(pyobj), Py_TPFLAGS_TYPE_SUBCLASS) #define PyClass_Check(pyobj) (Py_API(PyClass_Type) && (pyobj)->ob_type == Py_API(PyClass_Type)) @@ -78,11 +78,11 @@ /* * In pthread, the default value is NULL (== 0). * * In Win32 thread, the default value is 0 (initialized by TlsAlloc). */ - return (int)pycall_tls_get(without_gvl_key); + return pycall_tls_get(without_gvl_key) != (void*)0; } static inline int pycall_set_without_gvl(void) { @@ -105,10 +105,14 @@ result = rb_protect(func, arg, &state); pycall_set_with_gvl(); + if (state) { + rb_jump_tag(state); + } + return result; } static VALUE pycall_m_without_gvl(VALUE mod) @@ -408,11 +412,10 @@ VALUE cname, str; PyObject* pyobj = get_pyobj_ptr(obj); cname = rb_class_name(CLASS_OF(obj)); str = rb_sprintf("#<%"PRIsVALUE":%p type=%s addr=%p>", cname, (void*)obj, Py_TYPE(pyobj)->tp_name, pyobj); - OBJ_INFECT(str, obj); return str; } static VALUE @@ -860,10 +863,55 @@ res = Py_API(PyObject_HasAttrString)(pyobj, StringValueCStr(name)); return res ? Qtrue : Qfalse; } static VALUE +pycall_libpython_helpers_m_setattr(VALUE mod, VALUE pyptr, VALUE name, VALUE val) +{ + PyObject *pyobj, *pyval; + + if (!is_pycall_pyptr(pyptr)) { + rb_raise(rb_eTypeError, "PyCall::PyPtr is required"); + } + + pyobj = get_pyobj_ptr(pyptr); + + if (RB_TYPE_P(name, T_SYMBOL)) { + name = rb_sym_to_s(name); + } + + pyval = pycall_pyobject_from_ruby(val); + if (Py_API(PyObject_SetAttrString)(pyobj, StringValueCStr(name), pyval) == -1) { + pycall_pyerror_fetch_and_raise("PyObject_SetAttrString"); + } + + return Qnil; +} + +static VALUE +pycall_libpython_helpers_m_delattr(VALUE mod, VALUE pyptr, VALUE name) +{ + PyObject *pyobj; + + if (!is_pycall_pyptr(pyptr)) { + rb_raise(rb_eTypeError, "PyCall::PyPtr is required"); + } + + pyobj = get_pyobj_ptr(pyptr); + + if (RB_TYPE_P(name, T_SYMBOL)) { + name = rb_sym_to_s(name); + } + + if (Py_API(PyObject_DelAttrString)(pyobj, StringValueCStr(name)) == -1) { + pycall_pyerror_fetch_and_raise("PyObject_DelAttrString"); + } + + return Qnil; +} + +static VALUE pycall_libpython_helpers_m_callable_p(VALUE mod, VALUE pyptr) { PyObject *pyobj; int res; @@ -1075,11 +1123,11 @@ } static VALUE pycall_libpython_helpers_m_define_wrapper_method(VALUE mod, VALUE wrapper, VALUE name) { - VALUE pyptr, name_sym; + VALUE pyptr; PyObject *pyobj, *attr; char *name_cstr; pyptr = rb_attr_get(wrapper, rb_intern("@__pyptr__")); if (NIL_P(pyptr) || !is_pycall_pyptr(pyptr)) { @@ -1087,16 +1135,12 @@ } pyobj = get_pyobj_ptr(pyptr); if (RB_TYPE_P(name, T_SYMBOL)) { - name_sym = name; name = rb_sym_to_s(name); } - else if (RB_TYPE_P(name, T_STRING)) { - name_sym = rb_str_intern(name); - } name_cstr = StringValueCStr(name); if (name_cstr[RSTRING_LEN(name) - 1] == '=') { name_cstr[RSTRING_LEN(name) - 1] = '\0'; attr = Py_API(PyObject_GetAttrString)(pyobj, name_cstr); @@ -1187,11 +1231,11 @@ return v; } static VALUE -pycall_libpython_helpers_m_delitem(VALUE mod, VALUE pyptr, VALUE key, VALUE v) +pycall_libpython_helpers_m_delitem(VALUE mod, VALUE pyptr, VALUE key) { PyObject *pyobj, *pyobj_key; int res; pyobj = check_get_pyobj_ptr(pyptr, NULL); @@ -1200,11 +1244,11 @@ res = Py_API(PyObject_DelItem)(pyobj, pyobj_key); if (res == -1) { pycall_pyerror_fetch_and_raise("PyObject_DelItem"); } - return v; + return Qnil; } static VALUE pycall_libpython_helpers_m_str(VALUE mod, VALUE pyptr) { @@ -2015,10 +2059,12 @@ pycall_pyerror_fetch_and_raise(char const *format, ...) { va_list args; VALUE pyerror, msg; + RBIMPL_NONNULL_ARG(format); + pyerror = pycall_pyerror_fetch(); if (!NIL_P(pyerror)) rb_exc_raise(pyerror); va_start(args, format); @@ -2072,15 +2118,28 @@ return Py_API(PyString_FromFormatV)(format, vargs); } /* ==== Python ==== */ +int +pycall_PyObject_DelAttrString(PyObject *pyobj, const char *attr_name) +{ + /* PyObject_DelAttrString is defined by using PyObject_SetAttrString in CPython's abstract.h */ + return Py_API(PyObject_SetAttrString)(pyobj, attr_name, NULL); +} + static void init_python(void) { static char const *argv[1] = { "" }; + /* optional functions */ + if (! Py_API(PyObject_DelAttrString)) { + /* The case of PyObject_DelAttrString as a macro */ + Py_API(PyObject_DelAttrString) = pycall_PyObject_DelAttrString; + } + Py_API(Py_InitializeEx)(0); Py_API(PySys_SetArgvEx)(0, (char **)argv, 0); if (!Py_API(PyEval_ThreadsInitialized)()) { Py_API(PyEval_InitThreads)(); @@ -2234,11 +2293,11 @@ /* PyCall */ rb_define_module_function(mPyCall, "after_fork", pycall_after_fork, 0); - pycall_tls_create(&without_gvl_key); + pycall_tls_create((pycall_tls_key *)&without_gvl_key); rb_define_module_function(mPyCall, "without_gvl", pycall_m_without_gvl, 0); /* PyCall::PyPtr */ cPyPtr = rb_define_class_under(mPyCall, "PyPtr", rb_cBasicObject); @@ -2299,9 +2358,11 @@ rb_define_module_function(mHelpers, "import_module", pycall_libpython_helpers_m_import_module, -1); rb_define_module_function(mHelpers, "define_wrapper_method", pycall_libpython_helpers_m_define_wrapper_method, 2); rb_define_module_function(mHelpers, "compare", pycall_libpython_helpers_m_compare, 3); rb_define_module_function(mHelpers, "getattr", pycall_libpython_helpers_m_getattr, -1); rb_define_module_function(mHelpers, "hasattr?", pycall_libpython_helpers_m_hasattr_p, 2); + rb_define_module_function(mHelpers, "setattr", pycall_libpython_helpers_m_setattr, 3); + rb_define_module_function(mHelpers, "delattr", pycall_libpython_helpers_m_delattr, 2); rb_define_module_function(mHelpers, "callable?", pycall_libpython_helpers_m_callable_p, 1); rb_define_module_function(mHelpers, "call_object", pycall_libpython_helpers_m_call_object, -1); rb_define_module_function(mHelpers, "getitem", pycall_libpython_helpers_m_getitem, 2); rb_define_module_function(mHelpers, "setitem", pycall_libpython_helpers_m_setitem, 3); rb_define_module_function(mHelpers, "delitem", pycall_libpython_helpers_m_delitem, 2);