user [email protected] usertags 1145040 python3.15 thanks
Hi! While rebuilding the python related packages against the Python 3.15rc2 version I ran into this FTBFS [1]. I had to make a few changes to get the package back to a healthy state. - I applied upstream's commit 28f0910 [2]: Python: stop relying on SWIG's removed Py2 compat macros [ci:run_slow]. This is a different patch than the one proposed by Rafael, more invasive but as it's already applied upstream it makes sense to use that one. - The package repository was missing the `debian/*.install` files, so I added those - And I had to also add a missing python3-numpy dependency. I've applied these fixes in the sandbox [3] to verify that it builds successfully, these should be applied in Debian to get the package back to a healthy state. Happy hacking, [1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/TODO/ [2]: https://github.com/casadi/casadi/commit/28f0910eedc41861e8544d4c7590b67f934dd57c [3]: https://debusine.debian.net/debian/r-python-python3.15/ -- "Can you imagine what I would do if I could do all I can?" -- Sun Tzu Saludos /\/\ /\ >< `/
diff -Nru casadi-3.7.2+ds2/debian/casadi.install casadi-3.7.2+ds2/debian/casadi.install --- casadi-3.7.2+ds2/debian/casadi.install 2025-07-30 13:35:32.000000000 +0200 +++ casadi-3.7.2+ds2/debian/casadi.install 2026-09-08 14:27:12.000000000 +0200 @@ -1 +1 @@ -usr/bin +usr/bin/casadi-cli diff -Nru casadi-3.7.2+ds2/debian/changelog casadi-3.7.2+ds2/debian/changelog --- casadi-3.7.2+ds2/debian/changelog 2026-06-30 20:49:54.000000000 +0200 +++ casadi-3.7.2+ds2/debian/changelog 2026-09-08 14:27:12.000000000 +0200 @@ -1,3 +1,16 @@ +casadi (3.7.2+ds2-1.1) UNRELEASED; urgency=medium + + [ Bastian Germann ] + * Non-maintainer upload. + * d/copyright: delete empty line + + [ Maximiliano Curia ] + * Add upstream patch 0002-Python-stop-relying-on-SWIG-s-removed-Py2-compat-mac.patch + * commit missing install files + * Add numpy runtime dependency + + -- Maximiliano Curia <[email protected]> Tue, 08 Sep 2026 14:27:12 +0200 + casadi (3.7.2+ds2-1) unstable; urgency=medium * New upstream release. diff -Nru casadi-3.7.2+ds2/debian/control casadi-3.7.2+ds2/debian/control --- casadi-3.7.2+ds2/debian/control 2026-06-30 19:42:29.000000000 +0200 +++ casadi-3.7.2+ds2/debian/control 2026-09-08 14:27:12.000000000 +0200 @@ -74,6 +74,7 @@ Architecture: any Depends: python3, + python3-numpy, ${misc:Depends}, ${python3:Depends}, ${shlibs:Depends}, diff -Nru casadi-3.7.2+ds2/debian/copyright casadi-3.7.2+ds2/debian/copyright --- casadi-3.7.2+ds2/debian/copyright 2026-06-30 19:42:26.000000000 +0200 +++ casadi-3.7.2+ds2/debian/copyright 2026-09-08 14:27:12.000000000 +0200 @@ -173,7 +173,6 @@ modification, are permitted provided that the following conditions are met: . - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. . diff -Nru casadi-3.7.2+ds2/debian/libcasadi3.7.install casadi-3.7.2+ds2/debian/libcasadi3.7.install --- casadi-3.7.2+ds2/debian/libcasadi3.7.install 2025-07-30 14:26:40.000000000 +0200 +++ casadi-3.7.2+ds2/debian/libcasadi3.7.install 2026-09-08 14:27:12.000000000 +0200 @@ -1 +1 @@ -usr/lib/${DEB_HOST_MULTIARCH}/*.so.* +usr/lib/*/libcasadi*.so.* diff -Nru casadi-3.7.2+ds2/debian/libcasadi-dev.install casadi-3.7.2+ds2/debian/libcasadi-dev.install --- casadi-3.7.2+ds2/debian/libcasadi-dev.install 2025-06-24 16:25:41.000000000 +0200 +++ casadi-3.7.2+ds2/debian/libcasadi-dev.install 2026-09-08 14:27:12.000000000 +0200 @@ -1,4 +1,4 @@ -usr/include -usr/lib/${DEB_HOST_MULTIARCH}/cmake -usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig -usr/lib/*/lib*.so +usr/include/casadi +usr/lib/*/cmake/casadi +usr/lib/*/libcasadi*.so +usr/lib/*/pkgconfig/casadi.pc diff -Nru casadi-3.7.2+ds2/debian/patches/0002-Python-stop-relying-on-SWIG-s-removed-Py2-compat-mac.patch casadi-3.7.2+ds2/debian/patches/0002-Python-stop-relying-on-SWIG-s-removed-Py2-compat-mac.patch --- casadi-3.7.2+ds2/debian/patches/0002-Python-stop-relying-on-SWIG-s-removed-Py2-compat-mac.patch 1970-01-01 01:00:00.000000000 +0100 +++ casadi-3.7.2+ds2/debian/patches/0002-Python-stop-relying-on-SWIG-s-removed-Py2-compat-mac.patch 2026-09-08 14:27:12.000000000 +0200 @@ -0,0 +1,239 @@ +From: Joris Gillis <[email protected]> +Date: Thu, 20 Aug 2026 21:01:08 +0200 +Subject: Python: stop relying on SWIG's removed Py2 compat macros [ci:run_slow] + +SWIG 4.5.0 removed the Python 2 compatibility macros that pyhead.swg used +to inject into every generated wrapper, so casadi.i no longer compiles +with a current SWIG. Substitute the macro bodies as SWIG documents them: +PyString_FromString -> PyUnicode_FromString, PyInt_Check -> PyLong_Check, +PyInt_AsLong -> PyLong_AsLong. + +PyString_Check expanded to PyBytes_Check, not PyUnicode_Check, so its +three call sites need care rather than a rename: keep excluding bytes +from the "iterable of matrices" path (iterating b"ab" would silently +yield [97, 98]), and drop bytes from to_ptr(std::string) and the +std::map key check, where python_string_to_std_string fed a NULL from +PyUnicode_AsUTF8* straight into a std::string -- casadi.SX.sym(b"x") +segfaulted the interpreter. + +Harden python_string_to_std_string itself rather than leaving that a +caller-side convention: it now decodes to "" instead of dereferencing +NULL, for both a missing object and a failed decode. That closes a +second reachable crash -- handle_director_exception calls it on +PyObject_Str(pvalue), which returns NULL when the exception's __str__ +raises, and then Py_DECREF'd that NULL as well. + +Auditing the rest of the file for the same shape turned up two more: + +- the 1-D probe in to_ptr(std::vector) released its shape tuple only on + the reject path, so every 1-D numeric-like argument leaked a reference + per probe (measured: 3000 for 1000 conversions). It also fed a + possibly-NULL shape to PyTuple_Check. +- PyObjectHasClassName had the same unchecked-getattr pattern twice over + plus two bare Py_DECREFs. It has no callers anywhere in the tree or in + the generated wrappers, so drop it rather than harden dead code. + +Covered by typemaps.py test_bytes_typemaps and test_shape_attr_no_refleak, +and function.py test_Callback_unstringable_exception. + +Co-Authored-By: Claude Opus 5 <[email protected]> +Origin: upstream, https://github.com/casadi/casadi/commit/28f0910eedc41861e8544d4c7590b67f934dd57c +Applied-Upstream: 3.8.0 +--- + swig/casadi.i | 68 +++++++++++++++++++++++++++++--------------- + swig/python/casadi_numpy.hpp | 4 --- + 2 files changed, 45 insertions(+), 27 deletions(-) + +diff --git a/swig/casadi.i b/swig/casadi.i +index 7be64320c..d5b64090a 100644 +--- a/swig/casadi.i ++++ b/swig/casadi.i +@@ -109,16 +109,20 @@ + // SWIG_PYTHON_THREAD_END_BLOCK is not needed, destructor will release GIL + } + ++ // Decodes to "" rather than dereferencing NULL when str_py is absent or not a str + std::string python_string_to_std_string(PyObject *str_py) { ++ if (!str_py) return ""; + #if SWIG_VERSION < 0x040200 +- const char *str_char = SWIG_Python_str_AsChar(str_py); +- std::string str(str_char); +- SWIG_Python_str_DelForPy3(str_char); ++ const char *chars = SWIG_Python_str_AsChar(str_py); ++ std::string str(chars ? chars : ""); ++ SWIG_Python_str_DelForPy3(chars); + #else + PyObject *bytes = NULL; +- std::string str(SWIG_PyUnicode_AsUTF8AndSize(str_py, NULL, &bytes)); ++ const char *chars = SWIG_PyUnicode_AsUTF8AndSize(str_py, NULL, &bytes); ++ std::string str(chars ? chars : ""); + Py_XDECREF(bytes); + #endif ++ if (!chars) PyErr_Clear(); + return str; + } + +@@ -139,7 +143,7 @@ + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + PyObject* msg_py = PyObject_Str(pvalue); + msg = python_string_to_std_string(msg_py); +- Py_DECREF(msg_py); ++ Py_XDECREF(msg_py); + PyErr_Restore(ptype, pvalue, ptraceback); + PyErr_Print(); + #ifndef CASADI_WITH_PYTHON_GIL_RELEASE +@@ -684,7 +688,7 @@ namespace std { + GUESTOBJECT* full(const DM& m, bool simplify=false) { + #ifdef SWIGPYTHON + PyObject *p = from_ptr(&m); +- PyObject *method_name = PyString_FromString("toarray"); ++ PyObject *method_name = PyUnicode_FromString("toarray"); + PyObject *cr = PyObject_CallMethodObjArgs(p, method_name, (simplify? Py_True: Py_False), 0); + Py_DECREF(method_name); + Py_DECREF(p); +@@ -737,7 +741,7 @@ namespace std { + %#if PY_VERSION_HEX < 0x03070000 + PyObject* module = PyImport_AddModule("casadi"); + %#else +- PyObject* c_name = PyString_FromString("casadi"); ++ PyObject* c_name = PyUnicode_FromString("casadi"); + PyObject* module = PyImport_GetModule(c_name); + Py_DECREF(c_name); + %#endif +@@ -1273,15 +1277,18 @@ namespace std { + #ifdef SWIGPYTHON + + // Some built-in types are iterable +- if (PyDict_Check(p) || PyString_Check(p) || PySet_Check(p) || PyUnicode_Check(p)) return false; ++ // bytes is iterable but yields ints; walking it as a vector of numbers ++ // would silently turn b"ab" into [97, 98] instead of raising. ++ if (PyDict_Check(p) || PyBytes_Check(p) || PySet_Check(p) || PyUnicode_Check(p)) return false; + + // Make sure shape is 1D, if defined. ++ if (PyErr_Occurred()) PyErr_Clear(); // Clear pending exception before type check + if (PyObject_HasAttrString(p, "shape")) { + PyObject * shape = PyObject_GetAttrString(p, "shape"); +- if(!PyTuple_Check(shape) || PyTuple_Size(shape)!=1) { +- Py_DECREF(shape); +- return false; +- } ++ if (!shape) { PyErr_Clear(); return false; } ++ bool is_1d = PyTuple_Check(shape) && PyTuple_Size(shape)==1; ++ Py_DECREF(shape); ++ if (!is_1d) return false; + } + + // Iterator to the sequence +@@ -1554,7 +1561,9 @@ namespace std { + } + + #ifdef SWIGPYTHON +- if (PyString_Check(p) || PyUnicode_Check(p)) { ++ // str only: python_string_to_std_string goes through ++ // PyUnicode_AsUTF8*, which returns NULL for a bytes object. ++ if (PyUnicode_Check(p)) { + if (m) { + (*m)->clear(); + (*m)->append(python_string_to_std_string(p)); +@@ -1589,7 +1598,7 @@ namespace std { + + GUESTOBJECT* from_ptr(const std::string *a) { + #ifdef SWIGPYTHON +- return PyString_FromString(a->c_str()); ++ return PyUnicode_FromString(a->c_str()); + #elif defined(SWIGMATLAB) + return mxCreateString(a->c_str()); + #else +@@ -1614,23 +1623,40 @@ namespace std { + #ifdef SWIGPYTHON + + // Python casadi_int +- if (PyInt_Check(p)) { ++ if (PyLong_Check(p)) { + if (m) { +- (**m).start = PyInt_AsLong(p); ++ (**m).start = PyLong_AsLong(p); + (**m).stop = (**m).start+1; + if ((**m).stop==0) (**m).stop = std::numeric_limits<casadi_int>::max(); + } + return true; + } +- // Python slice ++ // Python slice - use Limited API compatible approach + if (PySlice_Check(p)) { +- PySliceObject *r = (PySliceObject*)(p); ++ Py_ssize_t start, stop, step; ++%#if PY_VERSION_HEX >= 0x03060100 ++ int res = PySlice_Unpack(p, &start, &stop, &step); ++%#else ++ // Python 2.7 and early Python 3.x use _PySlice_Unpack (private API) ++ int res = _PySlice_Unpack(p, &start, &stop, &step); ++%#endif ++ if (res < 0) { ++ return false; // TypeError already set by PySlice_Unpack ++ } ++ + if (m) { +- (**m).start = (r->start == Py_None || PyNumber_AsSsize_t(r->start, NULL) <= std::numeric_limits<int>::min()) +- ? std::numeric_limits<casadi_int>::min() : PyInt_AsLong(r->start); +- (**m).stop = (r->stop ==Py_None || PyNumber_AsSsize_t(r->stop, NULL)>= std::numeric_limits<int>::max()) +- ? std::numeric_limits<casadi_int>::max() : PyInt_AsLong(r->stop); +- if(r->step !=Py_None) (**m).step = PyInt_AsLong(r->step); ++ // Map sentinel values from PySlice_Unpack to CasADi's limits ++ // PySlice_Unpack returns PY_SSIZE_T_MIN or PY_SSIZE_T_MAX as sentinels ++ // depending on step direction, so check both extremes ++ (**m).start = (start == PY_SSIZE_T_MIN || start == PY_SSIZE_T_MAX) ++ ? std::numeric_limits<casadi_int>::min() ++ : static_cast<casadi_int>(start); ++ (**m).stop = (stop == PY_SSIZE_T_MAX || stop == PY_SSIZE_T_MIN) ++ ? std::numeric_limits<casadi_int>::max() ++ : static_cast<casadi_int>(stop); ++ if (step != 1) { ++ (**m).step = static_cast<casadi_int>(step); ++ } + } + return true; + } +@@ -1655,7 +1681,7 @@ namespace std { + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(p, &pos, &key, &value)) { +- if (!(PyString_Check(key) || PyUnicode_Check(key))) return false; ++ if (!PyUnicode_Check(key)) return false; + if (m) { + M *v=&(**m)[python_string_to_std_string(key)], *v2=v; + if (!casadi::to_ptr(value, &v)) return false; +@@ -1912,18 +1938,6 @@ namespace std { + + %fragment("casadi_dmatrix", "header", fragment="casadi_aux") { + namespace casadi { +-#ifdef SWIGPYTHON +- /** Check PyObjects by class name */ +- bool PyObjectHasClassName(PyObject* p, const char * name) { +- PyObject * classo = PyObject_GetAttrString( p, "__class__"); +- PyObject * classname = PyObject_GetAttrString( classo, "__name__"); +- +- bool ret = python_string_to_std_string(classname) == name; +- Py_DECREF(classo);Py_DECREF(classname); +- return ret; +- } +-#endif // SWIGPYTHON +- + bool to_ptr(GUESTOBJECT *p, DM** m) { + // Treat Null + if (is_null(p)) return false; +diff --git a/swig/python/casadi_numpy.hpp b/swig/python/casadi_numpy.hpp +index 2cdbd6e85..2f5ee9329 100644 +--- a/swig/python/casadi_numpy.hpp ++++ b/swig/python/casadi_numpy.hpp +@@ -21,10 +21,6 @@ + #define array_size(a,i) (PyArray_DIM(((PyArrayObject *)a),i)) + #define array_data(a) (PyArray_DATA(((PyArrayObject *)a))) + +-#if PY_MAJOR_VERSION >= 3 +-#define PyInt_Type PyLong_Type +-#endif +- + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and diff -Nru casadi-3.7.2+ds2/debian/patches/series casadi-3.7.2+ds2/debian/patches/series --- casadi-3.7.2+ds2/debian/patches/series 2026-06-30 20:22:49.000000000 +0200 +++ casadi-3.7.2+ds2/debian/patches/series 2026-09-08 14:27:12.000000000 +0200 @@ -1 +1,2 @@ 0001-Testsuite-force-python3.patch +0002-Python-stop-relying-on-SWIG-s-removed-Py2-compat-mac.patch diff -Nru casadi-3.7.2+ds2/debian/python3-casadi.install casadi-3.7.2+ds2/debian/python3-casadi.install --- casadi-3.7.2+ds2/debian/python3-casadi.install 2025-06-22 17:00:23.000000000 +0200 +++ casadi-3.7.2+ds2/debian/python3-casadi.install 2026-09-08 14:27:12.000000000 +0200 @@ -1 +1 @@ -usr/lib/python3 +usr/lib/python3/dist-packages/casadi

