From 19c081e3226716724c1774557431f4d6e00453fd Mon Sep 17 00:00:00 2001 From: frmdstryr Date: Sat, 18 Jan 2025 14:50:42 -0500 Subject: [PATCH 1/2] Refactor setattrbehavior calls --- atom/src/setattrbehavior.cpp | 86 +++++++----------------------------- 1 file changed, 17 insertions(+), 69 deletions(-) diff --git a/atom/src/setattrbehavior.cpp b/atom/src/setattrbehavior.cpp index b66b73eb..5439b274 100644 --- a/atom/src/setattrbehavior.cpp +++ b/atom/src/setattrbehavior.cpp @@ -268,18 +268,7 @@ _mangled_property_handler( Member* member, CAtom* atom, PyObject* value ) cppy::ptr name( PyUnicode_FromFormat( "_set_%s", suffix ) ); if( !name ) return -1; - cppy::ptr callable( PyObject_GetAttr( pyobject_cast( atom ), name.get() ) ); - if( !callable ) - { - if( PyErr_ExceptionMatches( PyExc_AttributeError ) ) - PyErr_SetString( PyExc_AttributeError, "can't set attribute" ); - return -1; - } - cppy::ptr argsptr( PyTuple_New( 1 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, cppy::incref( value ) ); - cppy::ptr ok( PyObject_Call( callable.get(), argsptr.get(), 0 ) ); + cppy::ptr ok( PyObject_CallMethodOneArg( pyobject_cast( atom ), name.get(), value ) ); if( !ok ) return -1; return 0; @@ -291,12 +280,8 @@ property_handler( Member* member, CAtom* atom, PyObject* value ) { if( member->setattr_context != Py_None ) { - cppy::ptr argsptr( PyTuple_New( 2 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, cppy::incref( pyobject_cast( atom ) ) ); - PyTuple_SET_ITEM( argsptr.get(), 1, cppy::incref( pyobject_cast( value ) ) ); - cppy::ptr ok( PyObject_Call( member->setattr_context, argsptr.get(), 0 ) ); + PyObject* args[] = { pyobject_cast( atom ), value }; + cppy::ptr ok( PyObject_Vectorcall( member->setattr_context, args, 2, 0 ) ); if( !ok ) return -1; return 0; @@ -308,17 +293,11 @@ property_handler( Member* member, CAtom* atom, PyObject* value ) int call_object_object_value_handler( Member* member, CAtom* atom, PyObject* value ) { - cppy::ptr valueptr( cppy::incref( value ) ); - valueptr = member->full_validate( atom, Py_None, valueptr.get() ); + cppy::ptr valueptr( member->full_validate( atom, Py_None, value ) ); if( !valueptr ) return -1; - cppy::ptr callable( cppy::incref( member->setattr_context ) ); - cppy::ptr argsptr( PyTuple_New( 2 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, cppy::incref( pyobject_cast( atom ) ) ); - PyTuple_SET_ITEM( argsptr.get(), 1, valueptr.release() ); - if( !callable.call( argsptr ) ) + PyObject* args[] = { pyobject_cast( atom ), valueptr.get() }; + if( !PyObject_Vectorcall( member->setattr_context, args, 2, 0 ) ) return -1; return 0; } @@ -327,18 +306,11 @@ call_object_object_value_handler( Member* member, CAtom* atom, PyObject* value ) int call_object_object_name_value_handler( Member* member, CAtom* atom, PyObject* value ) { - cppy::ptr valueptr( cppy::incref( value ) ); - valueptr = member->full_validate( atom, Py_None, valueptr.get() ); + cppy::ptr valueptr( member->full_validate( atom, Py_None, value ) ); if( !valueptr ) return -1; - cppy::ptr callable( cppy::incref( member->setattr_context ) ); - cppy::ptr argsptr( PyTuple_New( 3 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, cppy::incref( pyobject_cast( atom ) ) ); - PyTuple_SET_ITEM( argsptr.get(), 1, cppy::incref( member->name ) ); - PyTuple_SET_ITEM( argsptr.get(), 2, valueptr.release() ); - if( !callable.call( argsptr ) ) + PyObject* args[] = { pyobject_cast( atom ), member->name, valueptr.get() }; + if( !PyObject_Vectorcall( member->setattr_context, args, 3, 0 ) ) return -1; return 0; } @@ -347,18 +319,10 @@ call_object_object_name_value_handler( Member* member, CAtom* atom, PyObject* va int object_method_value_handler( Member* member, CAtom* atom, PyObject* value ) { - cppy::ptr valueptr( cppy::incref( value ) ); - valueptr = member->full_validate( atom, Py_None, valueptr.get() ); + cppy::ptr valueptr( member->full_validate( atom, Py_None, value ) ); if( !valueptr ) return -1; - cppy::ptr callable( PyObject_GetAttr( pyobject_cast( atom ), member->setattr_context ) ); - if( !callable ) - return -1; - cppy::ptr argsptr( PyTuple_New( 1 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, valueptr.release() ); - if( !callable.call( argsptr ) ) + if( !PyObject_CallMethodOneArg( pyobject_cast( atom ), member->setattr_context, valueptr.get() ) ) return -1; return 0; } @@ -367,19 +331,11 @@ object_method_value_handler( Member* member, CAtom* atom, PyObject* value ) int object_method_name_value_handler( Member* member, CAtom* atom, PyObject* value ) { - cppy::ptr valueptr( cppy::incref( value ) ); - valueptr = member->full_validate( atom, Py_None, valueptr.get() ); + cppy::ptr valueptr( member->full_validate( atom, Py_None, value ) ); if( !valueptr ) return -1; - cppy::ptr callable( PyObject_GetAttr( pyobject_cast( atom ), member->setattr_context ) ); - if( !callable ) - return -1; - cppy::ptr argsptr( PyTuple_New( 2 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, cppy::incref( member->name ) ); - PyTuple_SET_ITEM( argsptr.get(), 1, valueptr.release() ); - if( !callable.call( argsptr ) ) + PyObject* args[] = { pyobject_cast( atom ), member->name, valueptr.get() }; + if( !PyObject_VectorcallMethod( member->setattr_context, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, 0 ) ) return -1; return 0; } @@ -388,19 +344,11 @@ object_method_name_value_handler( Member* member, CAtom* atom, PyObject* value ) int member_method_object_value_handler( Member* member, CAtom* atom, PyObject* value ) { - cppy::ptr valueptr( cppy::incref( value ) ); - valueptr = member->full_validate( atom, Py_None, valueptr.get() ); + cppy::ptr valueptr( member->full_validate( atom, Py_None, value ) ); if( !valueptr ) return -1; - cppy::ptr callable( PyObject_GetAttr( pyobject_cast( member ), member->setattr_context ) ); - if( !callable ) - return -1; - cppy::ptr argsptr( PyTuple_New( 2 ) ); - if( !argsptr ) - return -1; - PyTuple_SET_ITEM( argsptr.get(), 0, cppy::incref( pyobject_cast( atom ) ) ); - PyTuple_SET_ITEM( argsptr.get(), 1, valueptr.release() ); - if( !callable.call( argsptr ) ) + PyObject* args[] = { pyobject_cast( member ), pyobject_cast( atom ), valueptr.get() }; + if( !PyObject_VectorcallMethod( member->setattr_context, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, 0 ) ) return -1; return 0; } From bd7395f8c700946dcd4fed4d3dd0a343c6246348 Mon Sep 17 00:00:00 2001 From: frmdstryr Date: Sat, 18 Jan 2025 15:33:46 -0500 Subject: [PATCH 2/2] Make sure all setattr handler results get checked --- atom/src/setattrbehavior.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/atom/src/setattrbehavior.cpp b/atom/src/setattrbehavior.cpp index 5439b274..36996936 100644 --- a/atom/src/setattrbehavior.cpp +++ b/atom/src/setattrbehavior.cpp @@ -297,7 +297,8 @@ call_object_object_value_handler( Member* member, CAtom* atom, PyObject* value ) if( !valueptr ) return -1; PyObject* args[] = { pyobject_cast( atom ), valueptr.get() }; - if( !PyObject_Vectorcall( member->setattr_context, args, 2, 0 ) ) + cppy::ptr ok( PyObject_Vectorcall( member->setattr_context, args, 2, 0 ) ); + if( !ok ) return -1; return 0; } @@ -310,7 +311,8 @@ call_object_object_name_value_handler( Member* member, CAtom* atom, PyObject* va if( !valueptr ) return -1; PyObject* args[] = { pyobject_cast( atom ), member->name, valueptr.get() }; - if( !PyObject_Vectorcall( member->setattr_context, args, 3, 0 ) ) + cppy::ptr ok( PyObject_Vectorcall( member->setattr_context, args, 3, 0 ) ); + if( !ok ) return -1; return 0; } @@ -322,7 +324,8 @@ object_method_value_handler( Member* member, CAtom* atom, PyObject* value ) cppy::ptr valueptr( member->full_validate( atom, Py_None, value ) ); if( !valueptr ) return -1; - if( !PyObject_CallMethodOneArg( pyobject_cast( atom ), member->setattr_context, valueptr.get() ) ) + cppy::ptr ok( PyObject_CallMethodOneArg( pyobject_cast( atom ), member->setattr_context, valueptr.get() ) ); + if ( !ok ) return -1; return 0; } @@ -335,7 +338,8 @@ object_method_name_value_handler( Member* member, CAtom* atom, PyObject* value ) if( !valueptr ) return -1; PyObject* args[] = { pyobject_cast( atom ), member->name, valueptr.get() }; - if( !PyObject_VectorcallMethod( member->setattr_context, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, 0 ) ) + cppy::ptr ok( PyObject_VectorcallMethod( member->setattr_context, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, 0 ) ); + if( !ok ) return -1; return 0; } @@ -348,7 +352,8 @@ member_method_object_value_handler( Member* member, CAtom* atom, PyObject* value if( !valueptr ) return -1; PyObject* args[] = { pyobject_cast( member ), pyobject_cast( atom ), valueptr.get() }; - if( !PyObject_VectorcallMethod( member->setattr_context, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, 0 ) ) + cppy::ptr ok( PyObject_VectorcallMethod( member->setattr_context, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, 0 ) ); + if( !ok ) return -1; return 0; }