Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-09-08 07:49:42 +0300
committerCampbell Barton <campbell@blender.org>2022-09-08 07:58:16 +0300
commit8a9d1f19ab1096b87e0da606c1ad623ac7bc0621 (patch)
tree1129e1dda94bcf5e72d6dbb5d2f6edd34ad1678b /source/blender/python/intern/bpy_interface.c
parent9f50bd20eb3b5a2d19ec6858755f1cda60927e84 (diff)
Python: ensure the runtime version is compatible WITH_PYTHON_MODULE
When Blender is built as a Python module, exit early if the major and minor versions don't match. Without this, the error message can be cryptic/unhelpful.
Diffstat (limited to 'source/blender/python/intern/bpy_interface.c')
-rw-r--r--source/blender/python/intern/bpy_interface.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 23fc0bcaeda..03fea3c6860 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -11,6 +11,10 @@
#include <Python.h>
#include <frameobject.h>
+#ifdef WITH_PYTHON_MODULE
+# include "pylifecycle.h" /* For `Py_Version`. */
+#endif
+
#include "MEM_guardedalloc.h"
#include "CLG_log.h"
@@ -807,6 +811,50 @@ static void bpy_module_delay_init(PyObject *bpy_proxy)
PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py));
}
+/**
+ * Raise an error and return false if the Python version used to compile Blender
+ * isn't compatible with the interpreter loading the `bpy` module.
+ */
+static bool bpy_module_ensure_compatible_version(void)
+{
+ /* First check the Python version used matches the major version that Blender was built with.
+ * While this isn't essential, the error message in this case may be cryptic and misleading.
+ * NOTE: using `Py_LIMITED_API` would remove the need for this, in practice it's
+ * unlikely Blender will ever used the limited API though. */
+# if PY_VERSION_HEX >= 0x030b0000 /* Python 3.11 & newer. */
+ const uint version_runtime = Py_Version;
+# else
+ uint version_runtime;
+ {
+ uint version_runtime_major = 0, version_runtime_minor = 0;
+ const char *version_str = Py_GetVersion();
+ if (sscanf(version_str, "%u.%u.", &version_runtime_major, &version_runtime_minor) != 2) {
+ /* Should never happen, raise an error to ensure this check never fails silently. */
+ PyErr_Format(PyExc_ImportError, "Failed to extract the version from \"%s\"", version_str);
+ return false;
+ }
+ version_runtime = (version_runtime_major << 24) | (version_runtime_minor << 16);
+ }
+# endif
+
+ uint version_compile_major = PY_VERSION_HEX >> 24;
+ uint version_compile_minor = ((PY_VERSION_HEX & 0x00ff0000) >> 16);
+ uint version_runtime_major = version_runtime >> 24;
+ uint version_runtime_minor = ((version_runtime & 0x00ff0000) >> 16);
+ if ((version_compile_major != version_runtime_major) ||
+ (version_compile_minor != version_runtime_minor)) {
+ PyErr_Format(PyExc_ImportError,
+ "The version of \"bpy\" was compiled with: "
+ "(%u.%u) is incompatible with: (%u.%u) used by the interpreter!",
+ version_compile_major,
+ version_compile_minor,
+ version_runtime_major,
+ version_runtime_minor);
+ return false;
+ }
+ return true;
+}
+
static void dealloc_obj_dealloc(PyObject *self);
static PyTypeObject dealloc_obj_Type;
@@ -824,6 +872,10 @@ PyMODINIT_FUNC PyInit_bpy(void);
PyMODINIT_FUNC PyInit_bpy(void)
{
+ if (!bpy_module_ensure_compatible_version()) {
+ return NULL; /* The error has been set. */
+ }
+
PyObject *bpy_proxy = PyModule_Create(&bpy_proxy_def);
/* Problem: