Extensions: remove intermediate operators for upgrade and sync

The buttons to upgrade or sync extensions called extension
operators via bpy.app.handlers, requiring awkward glue-code
which didn't show error reports in to the user.

Remove these operators and call the upgrade & sync operators directly.
This commit is contained in:
Campbell Barton
2024-06-07 16:30:31 +10:00
parent 9c60fe88fa
commit dc0e559cbb
7 changed files with 49 additions and 169 deletions

View File

@@ -300,26 +300,6 @@ def extenion_repos_sync(*_):
repo_status_text.from_message("Sync \"{:s}\"".format(active_repo.name), text)
@bpy.app.handlers.persistent
def extenion_repos_upgrade(*_):
# This is called from operators (create or an explicit call to sync)
# so calling a modal operator is "safe".
if (active_repo := repo_active_or_none()) is None:
return
print_debug("UPGRADE:", active_repo.name)
from contextlib import redirect_stdout
import io
stdout = io.StringIO()
with redirect_stdout(stdout):
bpy.ops.extensions.package_upgrade_all('INVOKE_DEFAULT', use_active_only=True)
if text := stdout.getvalue():
repo_status_text.from_message("Upgrade \"{:s}\"".format(active_repo.name), text)
@bpy.app.handlers.persistent
def extenion_repos_files_clear(directory, _):
# Perform a "safe" file deletion by only removing files known to be either
@@ -601,9 +581,6 @@ def register():
handlers = bpy.app.handlers._extension_repos_sync
handlers.append(extenion_repos_sync)
handlers = bpy.app.handlers._extension_repos_upgrade
handlers.append(extenion_repos_upgrade)
handlers = bpy.app.handlers._extension_repos_files_clear
handlers.append(extenion_repos_files_clear)
@@ -653,10 +630,6 @@ def unregister():
if extenion_repos_sync in handlers:
handlers.remove(extenion_repos_sync)
handlers = bpy.app.handlers._extension_repos_upgrade
if extenion_repos_upgrade in handlers:
handlers.remove(extenion_repos_upgrade)
handlers = bpy.app.handlers._extension_repos_files_clear
if extenion_repos_files_clear in handlers:
handlers.remove(extenion_repos_files_clear)

View File

@@ -916,7 +916,17 @@ def _repo_dir_and_index_get(repo_index, directory, report_fn):
return directory
def _extensions_maybe_online_action_poll_impl(cls, action_text):
def _extensions_maybe_online_action_poll_impl(cls, repo, action_text):
# Only operating on the active repository.
if repo is not None:
if not repo.enabled:
cls.poll_message_set("Active repository is disabled")
return False
if not repo.use_remote_url:
cls.poll_message_set("Local repositories do not support: {:s}".format(action_text))
return False
if not bpy.app.online_access:
cls.poll_message_set(
"Online access required to {:s}. {:s}".format(
@@ -1087,6 +1097,8 @@ class EXTENSIONS_OT_repo_sync(Operator, _ExtCmdMixIn):
class EXTENSIONS_OT_repo_sync_all(Operator, _ExtCmdMixIn):
# TODO: this text should be dynamic, changing when `use_active_only is True`.
# """Refresh the list of extensions for the active repository"""
"""Refresh the list of extensions for all the remote repositories"""
bl_idname = "extensions.repo_sync_all"
bl_label = "Check for Updates"
@@ -1098,8 +1110,9 @@ class EXTENSIONS_OT_repo_sync_all(Operator, _ExtCmdMixIn):
)
@classmethod
def poll(cls, _context):
return _extensions_maybe_online_action_poll_impl(cls, "check for updates")
def poll(cls, context):
repo = getattr(context, "extension_repo", None)
return _extensions_maybe_online_action_poll_impl(cls, repo, "check for updates")
def exec_command_iter(self, is_modal):
use_active_only = self.use_active_only
@@ -1168,6 +1181,8 @@ class EXTENSIONS_OT_repo_sync_all(Operator, _ExtCmdMixIn):
class EXTENSIONS_OT_package_upgrade_all(Operator, _ExtCmdMixIn):
# TODO: this text should be dynamic, changing when `use_active_only is True`.
# """Upgrade all the extensions to their latest version for the active repository"""
"""Upgrade all the extensions to their latest version for all the remote repositories"""
bl_idname = "extensions.package_upgrade_all"
bl_label = "Ext Package Upgrade All"
@@ -1182,8 +1197,9 @@ class EXTENSIONS_OT_package_upgrade_all(Operator, _ExtCmdMixIn):
)
@classmethod
def poll(cls, _context):
return _extensions_maybe_online_action_poll_impl(cls, "install updates")
def poll(cls, context):
repo = getattr(context, "extension_repo", None)
return _extensions_maybe_online_action_poll_impl(cls, repo, "install updates")
def exec_command_iter(self, is_modal):
from . import repo_cache_store

View File

@@ -22,6 +22,7 @@ from bpy.types import (
from bl_ui.space_userpref import (
USERPREF_PT_addons,
USERPREF_MT_extensions_active_repo,
)
from . import repo_status_text
@@ -1195,6 +1196,19 @@ def tags_panel_draw(panel, context):
col.prop(wm.extension_tags, "[\"{:s}\"]".format(escape_identifier(t)))
def extensions_repo_active_draw(self, context):
# Draw icon buttons on the right hand side of the UI-list.
from . import repo_active_or_none
layout = self.layout
# Allow the poll functions to only check against the active repository.
if (repo := repo_active_or_none()) is not None:
layout.context_pointer_set("extension_repo", repo)
layout.operator("extensions.repo_sync_all", text="", icon='FILE_REFRESH').use_active_only = True
layout.operator("extensions.package_upgrade_all", text="", icon='IMPORT').use_active_only = True
classes = (
# Pop-overs.
USERPREF_PT_extensions_filter,
@@ -1206,6 +1220,7 @@ classes = (
def register():
USERPREF_PT_addons.append(extensions_panel_draw)
USERPREF_PT_extensions_tags.append(tags_panel_draw)
USERPREF_MT_extensions_active_repo.append(extensions_repo_active_draw)
for cls in classes:
bpy.utils.register_class(cls)
@@ -1214,6 +1229,7 @@ def register():
def unregister():
USERPREF_PT_addons.remove(extensions_panel_draw)
USERPREF_PT_extensions_tags.remove(tags_panel_draw)
USERPREF_MT_extensions_active_repo.remove(extensions_repo_active_draw)
for cls in reversed(classes):
bpy.utils.unregister_class(cls)

View File

@@ -2122,6 +2122,15 @@ class USERPREF_PT_keymap(KeymapPanel, Panel):
# -----------------------------------------------------------------------------
# Extension Panels
class USERPREF_MT_extensions_active_repo(Menu):
bl_label = "Active Repository"
def draw(self, _context):
# Add-ons may extend.
pass
class USERPREF_PT_extensions_repos(Panel):
bl_label = "Repositories"
bl_options = {'HIDE_HEADER'}
@@ -2154,8 +2163,8 @@ class USERPREF_PT_extensions_repos(Panel):
props.index = active_repo_index
col.separator()
col.operator("preferences.extension_repo_sync", text="", icon='FILE_REFRESH')
col.operator("preferences.extension_repo_upgrade", text="", icon='IMPORT')
col.menu_contents("USERPREF_MT_extensions_active_repo")
try:
active_repo = None if active_repo_index < 0 else extensions.repos[active_repo_index]
@@ -2922,6 +2931,7 @@ classes = (
USERPREF_PT_addons,
USERPREF_MT_extensions_active_repo,
USERPREF_PT_extensions_repos,
USERPREF_PT_studiolight_lights,

View File

@@ -109,7 +109,6 @@ enum eCbEvent {
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE,
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST,
BKE_CB_EVT_EXTENSION_REPOS_SYNC,
BKE_CB_EVT_EXTENSION_REPOS_UPGRADE,
BKE_CB_EVT_EXTENSION_REPOS_FILES_CLEAR,
BKE_CB_EVT_TOT,
};

View File

@@ -577,86 +577,6 @@ static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Generic Extension Repository Utilities
* \{ */
static bool preferences_extension_check_for_updates_enabled_poll(bContext *C)
{
const bUserExtensionRepo *repo = BKE_preferences_extension_repo_find_index(
&U, U.active_extension_repo);
if ((G.f & G_FLAG_INTERNET_ALLOW) == 0) {
if ((G.f & G_FLAG_INTERNET_OVERRIDE_PREF_OFFLINE) != 0) {
CTX_wm_operator_poll_msg_set(
C, "Online access required to check for updates. Launch Blender without --offline-mode");
}
else {
CTX_wm_operator_poll_msg_set(C,
"Online access required to check for updates. Enable online "
"access in System preferences");
}
return false;
}
if (repo == nullptr) {
CTX_wm_operator_poll_msg_set(C, "No repositories available");
return false;
}
if ((repo->flag & USER_EXTENSION_REPO_FLAG_USE_REMOTE_URL) == 0) {
CTX_wm_operator_poll_msg_set(C, "Local repositories do not require refreshing");
return false;
}
if ((repo->flag & USER_EXTENSION_REPO_FLAG_DISABLED) != 0) {
CTX_wm_operator_poll_msg_set(C, "Active repository is disabled");
return false;
}
return true;
}
static bool preferences_extension_install_updates_enabled_poll(bContext *C)
{
const bUserExtensionRepo *repo = BKE_preferences_extension_repo_find_index(
&U, U.active_extension_repo);
if ((G.f & G_FLAG_INTERNET_ALLOW) == 0) {
if ((G.f & G_FLAG_INTERNET_OVERRIDE_PREF_OFFLINE) != 0) {
CTX_wm_operator_poll_msg_set(
C, "Online access required to install updates. Launch Blender without --offline-mode");
}
else {
CTX_wm_operator_poll_msg_set(C,
"Online access required to install updates. Enable online "
"access in System preferences");
}
return false;
}
if (repo == nullptr) {
CTX_wm_operator_poll_msg_set(C, "No repositories available");
return false;
}
if ((repo->flag & USER_EXTENSION_REPO_FLAG_USE_REMOTE_URL) == 0) {
CTX_wm_operator_poll_msg_set(C,
"Local repositories do not require manual update. Reload scripts "
"or restart Blender to see any updates");
return false;
}
if ((repo->flag & USER_EXTENSION_REPO_FLAG_DISABLED) != 0) {
CTX_wm_operator_poll_msg_set(C, "Active repository is disabled");
return false;
}
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Remove Extension Repository Operator
* \{ */
@@ -801,57 +721,6 @@ static void PREFERENCES_OT_extension_repo_remove(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Check for Extension Repository Updates Operator
* \{ */
static int preferences_extension_repo_sync_exec(bContext *C, wmOperator * /*op*/)
{
Main *bmain = CTX_data_main(C);
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_SYNC);
WM_event_add_notifier(C, NC_WINDOW, nullptr);
return OPERATOR_FINISHED;
}
static void PREFERENCES_OT_extension_repo_sync(wmOperatorType *ot)
{
ot->name = "Check for Updates";
ot->idname = "PREFERENCES_OT_extension_repo_sync";
ot->description = "Refresh the list of extensions for the active repository";
ot->exec = preferences_extension_repo_sync_exec;
ot->poll = preferences_extension_check_for_updates_enabled_poll;
ot->flag = OPTYPE_INTERNAL;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Update Extension Repository Operator
* \{ */
static int preferences_extension_repo_upgrade_exec(bContext *C, wmOperator * /*op*/)
{
Main *bmain = CTX_data_main(C);
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPGRADE);
WM_event_add_notifier(C, NC_WINDOW, nullptr);
return OPERATOR_FINISHED;
}
static void PREFERENCES_OT_extension_repo_upgrade(wmOperatorType *ot)
{
ot->name = "Install Available Updates for Repository";
ot->idname = "PREFERENCES_OT_extension_repo_upgrade";
ot->description = "Upgrade all the extensions to their latest version for the active repository";
ot->exec = preferences_extension_repo_upgrade_exec;
ot->poll = preferences_extension_install_updates_enabled_poll;
ot->flag = OPTYPE_INTERNAL;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Drop Extension Operator
* \{ */
@@ -1171,8 +1040,6 @@ void ED_operatortypes_userpref()
WM_operatortype_append(PREFERENCES_OT_extension_repo_add);
WM_operatortype_append(PREFERENCES_OT_extension_repo_remove);
WM_operatortype_append(PREFERENCES_OT_extension_repo_sync);
WM_operatortype_append(PREFERENCES_OT_extension_repo_upgrade);
WM_operatortype_append(PREFERENCES_OT_extension_url_drop);
WM_operatortype_append(PREFERENCES_OT_associate_blend);

View File

@@ -97,7 +97,6 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{"_extension_repos_update_pre", "on changes to extension repos (before)"},
{"_extension_repos_update_post", "on changes to extension repos (after)"},
{"_extension_repos_sync", "on creating or synchronizing the active repository"},
{"_extension_repos_upgrade", "on upgrading the active repository"},
{"_extension_repos_files_clear",
"remove files from the repository directory (uses as a string argument)"},