From 105103332422ca78b26af062c6aaff9d640d6eee Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 7 Nov 2023 21:33:18 +0100 Subject: [PATCH] libcalamares: create Python module libcalamares by hand From inside Calamares, register libcalamares to the interpreter by hand; from external Python processes the regular extension library hooks are called. Tested by running ./build/localmodule dummypython (which means that the shared library is not present in the current directory, so then `import libcalamares` fails if the module is not already registered -- a test scenario that previous attempt at module import missed). --- src/libcalamares/python/PythonJob.cpp | 36 ++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/python/PythonJob.cpp b/src/libcalamares/python/PythonJob.cpp index 4f00ca7fe..6c3a79c4a 100644 --- a/src/libcalamares/python/PythonJob.cpp +++ b/src/libcalamares/python/PythonJob.cpp @@ -22,6 +22,9 @@ namespace py = pybind11; +// Forward-declare function generated by PYBIND11_MODULE +static void pybind11_init_libcalamares( ::pybind11::module_& variable ); + namespace { @@ -242,7 +245,38 @@ Job::exec() // Import, but do not keep the handle lying around try { - auto calamaresModule = py::module_::import( "libcalamares" ); + // import() only works if the library can be found through + // normal Python import mechanisms -- and after installation, + // libcalamares can not be found. An alternative, like using + // PYBIND11_EMBEDDED_MODULE, falls foul of not being able + // to `import libcalamares` from external Python scripts, + // which are used in tests. + // + // auto calamaresModule = py::module_::import( "libcalamares" ); + // + // Using the constructor directly generates compiler warnings + // because this is deprecated. + // + // auto calamaresModule = py::module_("libcalamares"); + // + // So create it by hand, using code cribbed from pybind11/embed.h + // to register an extension module. This does not make it + // available to the current interpreter. + // + static ::pybind11::module_::module_def libcalamares_def; + auto calamaresModule = py::module_::create_extension_module( "libcalamares", nullptr, &libcalamares_def ); + pybind11_init_libcalamares( calamaresModule ); + + // Add libcalamares to the main namespace (as if it has already + // been imported) and also to sys.modules under its own name. + // Now `import libcalamares` in modules will find the already- + // loaded module. + auto scope = py::module_::import( "__main__" ).attr( "__dict__" ); + scope["libcalamares"] = calamaresModule; + + auto sys = scope["sys"].attr("modules"); + sys["libcalamares"] = calamaresModule; + calamaresModule.attr( "job" ) = Calamares::Python::JobProxy( this ); calamaresModule.attr( "globalstorage" ) = Calamares::Python::GlobalStorageProxy( JobQueue::instance()->globalStorage() );