From 87d569de595e27560102011437c3629a74c88756 Mon Sep 17 00:00:00 2001 From: David PAGNON Date: Tue, 11 Nov 2025 02:13:38 +0100 Subject: [PATCH 1/3] Accept paths as Path objects (not only strings) Python pathlib paths are much cleaner and easier to use than strings, and it is the recommended Python approach for manipulating paths since Python 3.6 (introduced in Python 3.4). When using OpenSim in other libraries that work with Path objects, it is a bit of a pain and a sourve of errors to have to convert the path into a string. The PR lets the OpenSim Python bindings accept paths both as strings and Path objects. Please note that I spent a full day trying to build it from source without success (I'm definitely lacking practice for this), and I feel like I need to let it go for now. I'm fairly confident that it would work, but I did not test it. At the very least, someone should try to build it and test this, at the very least: ```python import opensim as osim from pathlib import Path model = osim.Model("arm26.osim") model = osim.Model(Path("arm26.osim")) ``` --- Bindings/Python/swig/python_preliminaries.i | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Bindings/Python/swig/python_preliminaries.i b/Bindings/Python/swig/python_preliminaries.i index 91f636944c..6913ab0593 100644 --- a/Bindings/Python/swig/python_preliminaries.i +++ b/Bindings/Python/swig/python_preliminaries.i @@ -48,3 +48,22 @@ note: ## is a "glue" operator: `a ## b` --> `ab`. %} }; %enddef + +// Support for pathlib.Path objects +// ================================ +%typemap(in) std::string const & (std::string temp) { + if (PyUnicode_Check($input)) { + temp = std::string(PyUnicode_AsUTF8($input)); + $1 = &temp; + } else { + PyObject* fspath = PyOS_FSPath($input); + if (fspath != NULL) { + temp = std::string(PyUnicode_AsUTF8(fspath)); + Py_DECREF(fspath); + $1 = &temp; + } else { + PyErr_Clear(); + %argument_fail(SWIG_TypeError, "std::string const &", $symname, $argnum); + } + } +} From e86c0027fc86c55cda6cdbd8a8dcd16815dd2a37 Mon Sep 17 00:00:00 2001 From: David PAGNON Date: Tue, 11 Nov 2025 02:30:47 +0100 Subject: [PATCH 2/3] accept python path objects --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8b6a5390c..8fb151bc47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ performance and stability in wrapping solutions. - Implemented `generateDecorations()` for `Station` to allow visualization in the Simbody visualizer. (#4169) - Added `Component::removeComponent` and `Component::extractComponent` methods, which enable removing subcomponents that were previously added via `Component::addComponent` or the `` XML element (#4174). - Updated required language level to C++20. (#3929) +- Python API accepts Path objects instead of only strings v4.5.2 ====== From 7514b08dc96a92d02f2d339691c9666e8e68c449 Mon Sep 17 00:00:00 2001 From: David PAGNON Date: Tue, 11 Nov 2025 11:08:15 +0100 Subject: [PATCH 3/3] Fixed typemap declaration --- Bindings/Python/swig/python_preliminaries.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bindings/Python/swig/python_preliminaries.i b/Bindings/Python/swig/python_preliminaries.i index 6913ab0593..13c9a31f72 100644 --- a/Bindings/Python/swig/python_preliminaries.i +++ b/Bindings/Python/swig/python_preliminaries.i @@ -51,7 +51,7 @@ note: ## is a "glue" operator: `a ## b` --> `ab`. // Support for pathlib.Path objects // ================================ -%typemap(in) std::string const & (std::string temp) { +%typemap(in) std::string const & (std::string temp, int res = SWIG_OLDOBJ) { if (PyUnicode_Check($input)) { temp = std::string(PyUnicode_AsUTF8($input)); $1 = &temp;