diff --git a/source/blender/python/intern/bpy_app.cc b/source/blender/python/intern/bpy_app.cc index d833ec277c4..a186d9d792e 100644 --- a/source/blender/python/intern/bpy_app.cc +++ b/source/blender/python/intern/bpy_app.cc @@ -78,6 +78,10 @@ extern "C" char build_system[]; static PyTypeObject BlenderAppType; static PyStructSequence_Field app_info_fields[] = { + {"__name__", nullptr}, + {"__spec__", nullptr}, + {"__package__", nullptr}, + {"__loader__", nullptr}, {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 83, 1)"}, {"version_file", "The Blender version, as a tuple, last used to save a .blend file, compatible with " @@ -147,6 +151,10 @@ static PyObject *make_app_info() #define SetBytesItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str)) #define SetObjItem(obj) PyStructSequence_SET_ITEM(app_info, pos++, obj) + SetStrItem("bpy.app"); + SetObjItem(Py_INCREF_RET(Py_None)); + SetObjItem(Py_INCREF_RET(Py_None)); + SetObjItem(Py_INCREF_RET(Py_None)); SetObjItem( PyC_Tuple_Pack_I32({BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_VERSION_PATCH})); SetObjItem(PyC_Tuple_Pack_I32( @@ -198,6 +206,8 @@ static PyObject *make_app_info() SetObjItem(BPY_app_openvdb_struct()); SetObjItem(BPY_app_sdl_struct()); SetObjItem(BPY_app_build_options_struct()); + + /* pretend modules */ SetObjItem(BPY_app_handlers_struct()); SetObjItem(BPY_app_translations_struct()); diff --git a/source/blender/python/intern/bpy_app_handlers.cc b/source/blender/python/intern/bpy_app_handlers.cc index c9a8dff2f17..fd311c16a39 100644 --- a/source/blender/python/intern/bpy_app_handlers.cc +++ b/source/blender/python/intern/bpy_app_handlers.cc @@ -97,9 +97,14 @@ static PyStructSequence_Field app_cb_info_fields[] = { {"_extension_repos_update_post", "on changes to extension repos (after)"}, /* sets the permanent tag */ -#define APP_CB_OTHER_FIELDS 1 +#define APP_CB_OTHER_FIELDS 5 {"persistent", "Function decorator for callback functions not to be removed when loading new files"}, +/* module attributes */ + {"__name__", nullptr}, + {"__spec__", nullptr}, + {"__package__", nullptr}, + {"__loader__", nullptr}, {nullptr}, }; @@ -228,18 +233,29 @@ static PyObject *make_app_cb_info() return nullptr; } + /* for BKE_callbacks.h, validate fields and prepare sequence */ for (pos = 0; pos < BKE_CB_EVT_TOT; pos++) { if (app_cb_info_fields[pos].name == nullptr) { Py_FatalError("invalid callback slots 1"); } PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos] = PyList_New(0))); } + + /* custom sequence items */ if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != nullptr) { Py_FatalError("invalid callback slots 2"); } - /* custom function */ + /* persistent decorator func */ PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)&BPyPersistent_Type); + /* __name__ */ + PyStructSequence_SET_ITEM(app_cb_info, pos++, PyUnicode_FromString("bpy.app.handlers")); + /* __spec__ */ + PyStructSequence_SET_ITEM(app_cb_info, pos++, Py_INCREF_RET(Py_None)); + /* __package__ */ + PyStructSequence_SET_ITEM(app_cb_info, pos++, Py_INCREF_RET(Py_None)); + /* __loader__ */ + PyStructSequence_SET_ITEM(app_cb_info, pos++, Py_INCREF_RET(Py_None)); return app_cb_info; } diff --git a/source/blender/python/intern/bpy_app_translations.cc b/source/blender/python/intern/bpy_app_translations.cc index 48fc9617518..786df81bdd6 100644 --- a/source/blender/python/intern/bpy_app_translations.cc +++ b/source/blender/python/intern/bpy_app_translations.cc @@ -45,6 +45,9 @@ struct BlenderAppTranslations { PyObject *contexts; /** A readonly mapping {C context id: python id} (actually, a MappingProxy). */ PyObject *contexts_C_to_py; + + PyObject *module_name_attr; + /** * A Python dictionary containing all registered Python dictionaries * (order is more or less random, first match wins!). @@ -482,6 +485,26 @@ static PyMemberDef app_translations_members[] = { offsetof(BlenderAppTranslations, contexts_C_to_py), READONLY, app_translations_contexts_C_to_py_doc}, + {"__name__", + T_OBJECT, + offsetof(BlenderAppTranslations, module_name_attr), + READONLY, + nullptr}, + {"__spec__", + T_NONE, + 0, + READONLY, + nullptr}, + {"__package__", + T_NONE, + 0, + READONLY, + nullptr}, + {"__loader__", + T_NONE, + 0, + READONLY, + nullptr}, {nullptr}, }; @@ -765,6 +788,8 @@ static PyObject *app_translations_new(PyTypeObject *type, PyObject * /*args*/, P PyObject *py_ctxts; BLT_i18n_contexts_descriptor *ctxt; + _translations->module_name_attr = PyUnicode_FromString("bpy.app.translations"); + _translations->contexts = app_translations_contexts_make(); py_ctxts = _PyDict_NewPresized(ARRAY_SIZE(_contexts));