From 8f00d1eea0004ac6287320090eb3ec4e397d31dd Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 28 Mar 2025 12:57:39 -0400 Subject: [PATCH] fix: set __file__ on submodules (#5584) * fix: set __file__ on submodules The docs state ['The caller is responsible for setting a `__file__` attribute'](https://docs.python.org/3/c-api/module.html), but we were not doing that, which interferes with pickling objects in submodules using cloudpickle. Users previously had to set the `__file__` attributes manually, such as in https://github.com/scikit-hep/boost-histogram/blob/1fbbe1632e1665863b9c84b10edf6aa659a14bf1/src/boost_histogram/histogram.py#L83-L90. Signed-off-by: Henry Schreiner * fix: support GraalPy Signed-off-by: Henry Schreiner * fix: workaround only for GraalPython Signed-off-by: Henry Schreiner * Add GRAALPY_VERSION_NUM to GraalPy workaround * Fix "GRAALPY_VERSION_NUM not defined" issue ``` /Users/runner/work/pybind11/pybind11/include/pybind11/pybind11.h:1340:32: error: 'GRAALPY_VERSION_NUM' is not defined, evaluates to 0 [-Werror,-Wundef] ^ ``` Related ChatGPT conversation: https://chatgpt.com/share/67e6cb99-84b0-8008-99d6-aadc70242cf3 --------- Signed-off-by: Henry Schreiner Co-authored-by: Ralf W. Grosse-Kunstleve --- include/pybind11/pybind11.h | 13 +++++++++++++ tests/test_modules.py | 1 + 2 files changed, 14 insertions(+) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index caca57b3e..5f24dbde7 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1336,6 +1336,19 @@ public: if (doc && options::show_user_defined_docstrings()) { result.attr("__doc__") = pybind11::str(doc); } + +#if defined(GRAALVM_PYTHON) && (!defined(GRAALPY_VERSION_NUM) || GRAALPY_VERSION_NUM < 0x190000) + // GraalPy doesn't support PyModule_GetFilenameObject, + // so getting by attribute (see PR #5584) + handle this_module = m_ptr; + result.attr("__file__") = this_module.attr("__file__"); +#else + handle this_file = PyModule_GetFilenameObject(m_ptr); + if (!this_file) { + throw error_already_set(); + } + result.attr("__file__") = this_file; +#endif attr(name) = result; return result; } diff --git a/tests/test_modules.py b/tests/test_modules.py index ad898be89..f26c43da9 100644 --- a/tests/test_modules.py +++ b/tests/test_modules.py @@ -21,6 +21,7 @@ def test_nested_modules(): ) assert m.__name__ == "pybind11_tests.modules" assert ms.__name__ == "pybind11_tests.modules.subsubmodule" + assert m.__file__ == ms.__file__ assert ms.submodule_func() == "submodule_func()"