From b4ea8583ed34c7d30df85ea97ea86de0de422f72 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 10 Jun 2024 00:20:32 +1000 Subject: [PATCH] WM: correct logic for resetting add-ons & caching meta-data All add-ons were being scanned at startup, while this didn't cause errors it was noticeable with extensions where any errors in the manifest were being reported at startup, even when running with factory-startup (including blender's own tests). Address two issues: - The logic to "reset" add-ons, so as to match the preferences when reverting or resetting preferences always ran on startup. This occurred because a check for Python being initialized was incorrectly used to detect that this wasn't the first time preferences were being loaded (regression in [0]). - Resetting add-ons scanned all add-ons (including disabled add-ons) to ensure their module cache is up to date. Since this the cache is lazily initialized, it's simpler to set it as uninitialized as resetting the add-ons doesn't require the cached meta-data. [0]: 497bc4d19977abc7b9e2c0f5024a23057e680954 --- scripts/modules/addon_utils.py | 5 +++-- scripts/startup/bl_operators/userpref.py | 3 +++ source/blender/windowmanager/intern/wm_files.cc | 13 ++++++++----- source/blender/windowmanager/intern/wm_init_exit.cc | 1 + source/blender/windowmanager/wm_files.hh | 5 +++++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/scripts/modules/addon_utils.py b/scripts/modules/addon_utils.py index f4edb440e80..928f17ba236 100644 --- a/scripts/modules/addon_utils.py +++ b/scripts/modules/addon_utils.py @@ -536,8 +536,9 @@ def reset_all(*, reload_scripts=False): """ import sys - # initializes addons_fake_modules - modules_refresh() + # Ensures stale `addons_fake_modules` isn't used. + modules._is_first = True + addons_fake_modules.clear() for path, pkg_id in _paths_with_extension_repos(): if not pkg_id: diff --git a/scripts/startup/bl_operators/userpref.py b/scripts/startup/bl_operators/userpref.py index 8c4837d2736..42bb822e7d9 100644 --- a/scripts/startup/bl_operators/userpref.py +++ b/scripts/startup/bl_operators/userpref.py @@ -852,6 +852,8 @@ class PREFERENCES_OT_addon_expand(Operator): addon_module_name = self.module + # Ensure `addons_fake_modules` is set. + _modules = addon_utils.modules(refresh=False) mod = addon_utils.addons_fake_modules.get(addon_module_name) if mod is not None: bl_info = addon_utils.module_bl_info(mod) @@ -876,6 +878,7 @@ class PREFERENCES_OT_addon_show(Operator): addon_module_name = self.module + # Ensure `addons_fake_modules` is set. _modules = addon_utils.modules(refresh=False) mod = addon_utils.addons_fake_modules.get(addon_module_name) if mod is not None: diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index bd6daebd385..1ccf2dcaeb9 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -671,6 +671,7 @@ struct wmFileReadPost_Params { /* Used by #wm_homefile_read_post. */ uint success : 1; uint is_alloc : 1; + uint is_first_time : 1; }; /** @@ -701,11 +702,10 @@ static void wm_file_read_post(bContext *C, #ifdef WITH_PYTHON if (is_startup_file) { - /* On startup (by default), Python won't have been initialized. - * - * The following block handles data & preferences being reloaded + /* The following block handles data & preferences being reloaded * which requires resetting some internal variables. */ - if (CTX_py_init_get(C)) { + if (!params->is_first_time) { + BLI_assert(CTX_py_init_get(C)); bool reset_all = use_userdef; if (use_userdef || reset_app_template) { /* Only run when we have a template path found. */ @@ -1249,7 +1249,8 @@ void wm_homefile_read_ex(bContext *C, if (use_userdef || reset_app_template) { #ifdef WITH_PYTHON /* This only runs once Blender has already started. */ - if (CTX_py_init_get(C)) { + if (!params_homefile->is_first_time) { + BLI_assert(CTX_py_init_get(C)); /* This is restored by 'wm_file_read_post', disable before loading any preferences * so an add-on can read their own preferences when un-registering, * and use new preferences if/when re-registering, see #67577. @@ -1502,6 +1503,8 @@ void wm_homefile_read_ex(bContext *C, params_file_read_post.use_userdef = use_userdef; params_file_read_post.is_startup_file = true; params_file_read_post.is_factory_startup = is_factory_startup; + params_file_read_post.is_first_time = params_homefile->is_first_time; + params_file_read_post.reset_app_template = reset_app_template; params_file_read_post.success = success; diff --git a/source/blender/windowmanager/intern/wm_init_exit.cc b/source/blender/windowmanager/intern/wm_init_exit.cc index d675461490b..4eff54aa44a 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.cc +++ b/source/blender/windowmanager/intern/wm_init_exit.cc @@ -276,6 +276,7 @@ void WM_init(bContext *C, int argc, const char **argv) read_homefile_params.use_empty_data = false; read_homefile_params.filepath_startup_override = nullptr; read_homefile_params.app_template_override = WM_init_state_app_template_get(); + read_homefile_params.is_first_time = true; wm_homefile_read_ex(C, &read_homefile_params, nullptr, ¶ms_file_read_post); diff --git a/source/blender/windowmanager/wm_files.hh b/source/blender/windowmanager/wm_files.hh index c365b7c4ba1..54e784041f7 100644 --- a/source/blender/windowmanager/wm_files.hh +++ b/source/blender/windowmanager/wm_files.hh @@ -42,6 +42,11 @@ struct wmHomeFileRead_Params { * Useful for automated content generation, so the file starts without data. */ unsigned int use_empty_data : 1; + /** + * When true, this is the first time the home file is read. + * In this case resetting the previous state can be skipped. + */ + unsigned int is_first_time : 1; /** * Optional path pointing to an alternative blend file (may be NULL). */