diff --git a/scripts/addons_core/bl_pkg/bl_extension_ops.py b/scripts/addons_core/bl_pkg/bl_extension_ops.py index 67af7279224..ffc5433eab1 100644 --- a/scripts/addons_core/bl_pkg/bl_extension_ops.py +++ b/scripts/addons_core/bl_pkg/bl_extension_ops.py @@ -2442,7 +2442,19 @@ class EXTENSIONS_OT_package_install_files(Operator, _ExtCmdMixIn): "repo_directory", "pkg_id_sequence" ) + + # Dropping a file-path stores values in the class instance, values used are as follows: + # + # - None: Unset (not dropping), this value is read from the class. + # - (pkg_id, pkg_type): Drop values have been extracted from the ZIP file. + # Where the `pkg_id` is the ID in the extensions manifest and the `pkg_type` + # is the type of extension see `rna_prop_enable_on_install_type_map` keys. _drop_variables = None + # Used when dropping legacy add-ons: + # + # - None: Unset, not dropping a legacy add-on. + # - True: Drop treats the `filepath` as a legacy add-on. + # `_drop_variables` will be None. _legacy_drop = None filter_glob: StringProperty(default="*.zip;*.py", options={'HIDDEN'}) @@ -2895,6 +2907,17 @@ class EXTENSIONS_OT_package_install(Operator, _ExtCmdMixIn): bl_label = "Install Extension" __slots__ = _ExtCmdMixIn.cls_slots + # Dropping a URL stores values in the class instance, values used are as follows: + # + # - None: Unset (not-dropping), this value is read from the class. + # - A tuple containing values needed to execute the drop: + # `(repo_index: int, repo_name: str, pkg_id: str, item_remote: PkgManifest_Normalized)`. + # + # NOTE: these values aren't set immediately when dropping as they + # require the local repository to sync first, so the up to date meta-data + # from the URL can be used to ensure the dropped extension is known + # and any errors are based on up to date information. + # _drop_variables = None # Optional draw & keyword-arguments, return True to terminate drawing. _draw_override = None diff --git a/scripts/addons_core/bl_pkg/bl_extension_utils.py b/scripts/addons_core/bl_pkg/bl_extension_utils.py index 8434fd7d66a..78500a34302 100644 --- a/scripts/addons_core/bl_pkg/bl_extension_utils.py +++ b/scripts/addons_core/bl_pkg/bl_extension_utils.py @@ -896,6 +896,28 @@ class CommandBatch_StatusFlag(NamedTuple): class CommandBatch: + """ + This class manages running command-line programs as sub-processes, abstracting away process management, + performing non-blocking reads to access JSON output. + + The sub-processes must conform to the following constraints: + + - Only output JSON to the STDOUT. + - Exit gracefully when: SIGINT signal is sent + (``signal.CTRL_BREAK_EVENT`` on WIN32). + - Errors must be caught and forwarded as JSON error messages. + Unhandled exceptions are not expected and and will produce ugly + messages from the STDERR output. + + The user of this class creates the class with all known jobs, + setting the limit for the number of jobs that run simultaneously. + + The caller can then monitor the processes: + - By calling ``exec_blocking``. + - Or by periodically calling ``exec_non_blocking``. + + Canceling is performed by calling ``exec_non_blocking`` with ``request_exit=True``. + """ __slots__ = ( "title", diff --git a/scripts/addons_core/bl_pkg/cli/blender_ext.py b/scripts/addons_core/bl_pkg/cli/blender_ext.py index 5b4b7c0ee56..3790dd25dc7 100755 --- a/scripts/addons_core/bl_pkg/cli/blender_ext.py +++ b/scripts/addons_core/bl_pkg/cli/blender_ext.py @@ -2446,6 +2446,24 @@ def repository_filter_skip( skip_message_fn: Callable[[str], None] | None, error_fn: Callable[[Exception], None], ) -> bool: + """ + This function takes an ``item`` which represents un-validated extension meta-data. + Return True when the extension should be excluded. + + The meta-data is a subset of the ``blender_manifest.toml`` which is extracted + into the ``index.json`` hosted by a remote server. + + Filtering will exclude extensions when: + + - They're incompatible with Blender, Python or the platform defined by the ``filter_*`` arguments. + ``skip_message_fn`` callback will run with the cause of the incompatibility. + - The meta-data is malformed, it doesn't confirm to ``blender_manifest.toml`` data-types. + ``error_fn`` callback will run with the cause of the error. + + This is used so Blender's extensions listing only shows compatible extensions as well as + reporting errors if the user attempts to install an extension which isn't compatible with their system. + """ + if (platforms := item.get("platforms")) is not None: if not isinstance(platforms, list): # Possibly noisy, but this should *not* be happening on a regular basis.