@@ -104,12 +104,54 @@ _check_tuple_item_is_NULL(PyObject *Py_UNUSED(module), PyObject *args)
104104}
105105
106106
107+ static PyObject *
108+ tuple_fromarray (PyObject * Py_UNUSED (module ), PyObject * args )
109+ {
110+ PyObject * src ;
111+ if (!PyArg_ParseTuple (args , "O!" , & PyTuple_Type , & src )) {
112+ return NULL ;
113+ }
114+
115+ Py_ssize_t size = PyTuple_GET_SIZE (src );
116+ PyObject * * array = PyMem_Malloc (size * sizeof (PyObject * * ));
117+ if (array == NULL ) {
118+ PyErr_NoMemory ();
119+ return NULL ;
120+ }
121+ for (Py_ssize_t i = 0 ; i < size ; i ++ ) {
122+ array [i ] = Py_NewRef (PyTuple_GET_ITEM (src , i ));
123+ }
124+
125+ PyObject * tuple = PyTuple_FromArray (array , size );
126+ if (tuple == NULL ) {
127+ goto done ;
128+ }
129+
130+ for (Py_ssize_t i = 0 ; i < size ; i ++ ) {
131+ // check that the array is not modified
132+ assert (array [i ] == PyTuple_GET_ITEM (src , i ));
133+
134+ // check that the array was copied properly
135+ assert (PyTuple_GET_ITEM (tuple , i ) == array [i ]);
136+ }
137+
138+ done :
139+ for (Py_ssize_t i = 0 ; i < size ; i ++ ) {
140+ Py_DECREF (array [i ]);
141+ }
142+ PyMem_Free (array );
143+
144+ return tuple ;
145+ }
146+
147+
107148static PyMethodDef test_methods [] = {
108149 {"tuple_get_size" , tuple_get_size , METH_O },
109150 {"tuple_get_item" , tuple_get_item , METH_VARARGS },
110151 {"tuple_set_item" , tuple_set_item , METH_VARARGS },
111152 {"_tuple_resize" , _tuple_resize , METH_VARARGS },
112153 {"_check_tuple_item_is_NULL" , _check_tuple_item_is_NULL , METH_VARARGS },
154+ {"tuple_fromarray" , tuple_fromarray , METH_VARARGS },
113155 {NULL },
114156};
115157
0 commit comments