@@ -183,30 +183,49 @@ static PyObject *s_cbor_encoder_write_pyobject(struct aws_cbor_encoder *encoder,
183183 /**
184184 * TODO: timestamp <-> datetime?? Decimal fraction <-> decimal??
185185 */
186- if (PyLong_CheckExact (py_object )) {
187- return s_cbor_encoder_write_pylong (encoder , py_object );
188- } else if (PyFloat_CheckExact (py_object )) {
189- return s_cbor_encoder_write_pyobject_as_float (encoder , py_object );
190- } else if (PyBool_Check (py_object )) {
191- return s_cbor_encoder_write_pyobject_as_bool (encoder , py_object );
192- } else if (PyBytes_CheckExact (py_object )) {
193- return s_cbor_encoder_write_pyobject_as_bytes (encoder , py_object );
194- } else if (PyUnicode_Check (py_object )) {
186+
187+ /* Handle None first as it's a singleton, not a type */
188+ if (py_object == Py_None ) {
189+ aws_cbor_encoder_write_null (encoder );
190+ Py_RETURN_NONE ;
191+ }
192+
193+ /* Get type once for efficiency - PyObject_Type returns a new reference */
194+ /* https://docs.python.org/3/c-api/structures.html#c.Py_TYPE is not a stable API until 3.14, so that we cannot use
195+ * it. */
196+ PyObject * type = PyObject_Type (py_object );
197+ if (!type ) {
198+ return NULL ;
199+ }
200+
201+ PyObject * result = NULL ;
202+
203+ /* Exact type matches first (no subclasses) */
204+ if (type == (PyObject * )& PyLong_Type ) {
205+ result = s_cbor_encoder_write_pylong (encoder , py_object );
206+ } else if (type == (PyObject * )& PyFloat_Type ) {
207+ result = s_cbor_encoder_write_pyobject_as_float (encoder , py_object );
208+ } else if (type == (PyObject * )& PyBool_Type ) {
209+ result = s_cbor_encoder_write_pyobject_as_bool (encoder , py_object );
210+ } else if (type == (PyObject * )& PyBytes_Type ) {
211+ result = s_cbor_encoder_write_pyobject_as_bytes (encoder , py_object );
212+ } else if (PyType_IsSubtype ((PyTypeObject * )type , & PyUnicode_Type )) {
195213 /* Allow subclasses of `str` */
196- return s_cbor_encoder_write_pyobject_as_text (encoder , py_object );
197- } else if (PyList_Check ( py_object )) {
214+ result = s_cbor_encoder_write_pyobject_as_text (encoder , py_object );
215+ } else if (PyType_IsSubtype (( PyTypeObject * ) type , & PyList_Type )) {
198216 /* Write py_list, allow subclasses of `list` */
199- return s_cbor_encoder_write_pylist (encoder , py_object );
200- } else if (PyDict_Check ( py_object )) {
217+ result = s_cbor_encoder_write_pylist (encoder , py_object );
218+ } else if (PyType_IsSubtype (( PyTypeObject * ) type , & PyDict_Type )) {
201219 /* Write py_dict, allow subclasses of `dict` */
202- return s_cbor_encoder_write_pydict (encoder , py_object );
203- } else if (py_object == Py_None ) {
204- aws_cbor_encoder_write_null (encoder );
220+ result = s_cbor_encoder_write_pydict (encoder , py_object );
205221 } else {
206- PyErr_Format (PyExc_ValueError , "Not supported type %R" , (PyObject * )Py_TYPE (py_object ));
222+ /* Unsupported type */
223+ PyErr_Format (PyExc_ValueError , "Not supported type %R" , type );
207224 }
208225
209- Py_RETURN_NONE ;
226+ /* Release the type reference */
227+ Py_DECREF (type );
228+ return result ;
210229}
211230
212231/*********************************** BINDINGS ***********************************************/
0 commit comments