diff --git a/common/ayon_common/distribution/addon_distribution.py b/common/ayon_common/distribution/addon_distribution.py index dba6c20193..19aec2b031 100644 --- a/common/ayon_common/distribution/addon_distribution.py +++ b/common/ayon_common/distribution/addon_distribution.py @@ -322,22 +322,6 @@ class AyonServerDownloader(SourceDownloader): os.remove(filepath) -def get_addons_info(): - """Returns list of addon information from Server - - Returns: - List[AddonInfo]: List of metadata for addons sent from server, - parsed in AddonInfo objects - """ - - addons_info = [] - for addon in ayon_api.get_addons_info(details=True)["addons"]: - addon_info = AddonInfo.from_dict(addon) - if addon_info is not None: - addons_info.append(addon_info) - return addons_info - - def get_dependency_package(package_name=None): """Returns info about currently used dependency package. @@ -745,13 +729,16 @@ class AyonDistribution: Arguments are available for testing of the class. Args: - addon_dirpath (str): Where addons will be stored. - dependency_dirpath (str): Where dependencies will be stored. - dist_factory (DownloadFactory): Factory which cares about downloading - of items based on source type. - addons_info (List[AddonInfo]): List of prepared addons info. - dependency_package_info (Union[Dict[str, Any], None]): Dependency - package info from server. Defaults to '-1'. + addon_dirpath (Optional[str]): Where addons will be stored. + dependency_dirpath (Optional[str]): Where dependencies will be stored. + dist_factory (Optional[DownloadFactory]): Factory which cares about + downloading of items based on source type. + addons_info (Optional[List[AddonInfo]]): List of prepared addons' info. + dependency_package_info (Optional[Union[Dict[str, Any], None]]): Info + about package from server. Defaults to '-1'. + use_staging (Optional[bool]): Use staging versions of an addon. + If not passed, an environment variable 'OPENPYPE_USE_STAGING' is + checked for value '1'. """ def __init__( @@ -761,6 +748,7 @@ class AyonDistribution: dist_factory=None, addons_info=None, dependency_package_info=-1, + use_staging=None ): self._addons_dirpath = addon_dirpath or get_addons_dir() self._dependency_dirpath = dependency_dirpath or get_dependencies_dir() @@ -777,6 +765,13 @@ class AyonDistribution: self._addons_dist_items = None self._dependency_package = dependency_package_info self._dependency_dist_item = -1 + self._use_staging = use_staging + + @property + def use_staging(self): + if self._use_staging is None: + self._use_staging = os.getenv("OPENPYPE_USE_STAGING") == "1" + return self._use_staging @property def log(self): @@ -803,7 +798,7 @@ class AyonDistribution: addons_info = {} server_addons_info = ayon_api.get_addons_info(details=True) for addon in server_addons_info["addons"]: - addon_info = AddonInfo.from_dict(addon) + addon_info = AddonInfo.from_dict(addon, self.use_staging) if addon_info is None: continue addons_info[addon_info.full_name] = addon_info diff --git a/common/ayon_common/distribution/addon_info.py b/common/ayon_common/distribution/addon_info.py index 6da6f11ead..74f7b11f7f 100644 --- a/common/ayon_common/distribution/addon_info.py +++ b/common/ayon_common/distribution/addon_info.py @@ -98,19 +98,32 @@ class AddonInfo(object): authors = attr.ib(default=None) @classmethod - def from_dict(cls, data): - sources = [] - unknown_sources = [] + def from_dict_by_version(cls, data, addon_version): + """Addon info for specific version. - production_version = data.get("productionVersion") - if not production_version: + Args: + data (dict[str, Any]): Addon information from server. Should + contain information about every version under 'versions'. + addon_version (str): Addon version for which is info requested. + + Returns: + Union[AddonInfo, None]: Addon info, or None if version is not + available. + """ + + if not addon_version: return None # server payload contains info about all versions - # active addon must have 'productionVersion' and matching version info - version_data = data.get("versions", {})[production_version] + version_data = data.get("versions", {}).get(addon_version) + if not version_data: + return None + source_info = version_data.get("clientSourceInfo") require_distribution = source_info is not None + + sources = [] + unknown_sources = [] for source in (source_info or []): addon_source = convert_source(source) if addon_source is not None: @@ -119,10 +132,10 @@ class AddonInfo(object): unknown_sources.append(source) print(f"Unknown source {source.get('type')}") - full_name = "{}_{}".format(data["name"], production_version) + full_name = "{}_{}".format(data["name"], addon_version) return cls( name=data.get("name"), - version=production_version, + version=addon_version, full_name=full_name, require_distribution=require_distribution, sources=sources, @@ -134,6 +147,29 @@ class AddonInfo(object): authors=data.get("authors") ) + @classmethod + def from_dict(cls, data, use_staging=False): + """Get Addon information for production or staging version. + + Args: + data (dict[str, Any]): Addon information from server. Should + contain information about every version under 'versions'. + use_staging (bool): Use staging version if set to 'True' instead + of production. + + Returns: + Union[AddonInfo, None]: Addon info, or None if version is not + set or available. + """ + + # Active addon must have 'productionVersion' or 'stagingVersion' + # and matching version info. + if use_staging: + addon_version = data.get("stagingVersion") + else: + addon_version = data.get("productionVersion") + return cls.from_dict_by_version(data, addon_version) + @attr.s class DependencyItem(object): diff --git a/common/ayon_common/resources/AYON_staging.png b/common/ayon_common/resources/AYON_staging.png new file mode 100644 index 0000000000..75dadfd56c Binary files /dev/null and b/common/ayon_common/resources/AYON_staging.png differ diff --git a/common/ayon_common/resources/__init__.py b/common/ayon_common/resources/__init__.py index ca61295b94..21e5fef6b2 100644 --- a/common/ayon_common/resources/__init__.py +++ b/common/ayon_common/resources/__init__.py @@ -10,6 +10,8 @@ def get_resource_path(*args): def get_icon_path(): + if os.environ.get("OPENPYPE_USE_STAGING") == "1": + return get_resource_path("AYON_staging.png") return get_resource_path("AYON.png") diff --git a/openpype/lib/openpype_version.py b/openpype/lib/openpype_version.py index e052002468..bdf7099f61 100644 --- a/openpype/lib/openpype_version.py +++ b/openpype/lib/openpype_version.py @@ -13,6 +13,7 @@ import os import sys import openpype.version +from openpype import AYON_SERVER_ENABLED from .python_module_tools import import_filepath @@ -88,6 +89,9 @@ def is_running_staging(): bool: Using staging version or not. """ + if AYON_SERVER_ENABLED: + return is_staging_enabled() + if os.environ.get("OPENPYPE_IS_STAGING") == "1": return True diff --git a/openpype/modules/base.py b/openpype/modules/base.py index c1e928ff48..ab18c15f9a 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -34,8 +34,9 @@ from openpype.settings.lib import ( from openpype.lib import ( Logger, import_filepath, - import_module_from_dirpath + import_module_from_dirpath, ) +from openpype.lib.openpype_version import is_staging_enabled from .interfaces import ( OpenPypeInterface, @@ -353,9 +354,13 @@ def _load_ayon_addons(openpype_modules, modules_key, log): )) return v3_addons_to_skip + version_key = ( + "stagingVersion" if is_staging_enabled() + else "productionVersion" + ) for addon_info in addons_info: addon_name = addon_info["name"] - addon_version = addon_info.get("productionVersion") + addon_version = addon_info.get(version_key) if not addon_version: continue diff --git a/openpype/resources/__init__.py b/openpype/resources/__init__.py index 77cc0deaa2..b8671f517a 100644 --- a/openpype/resources/__init__.py +++ b/openpype/resources/__init__.py @@ -50,7 +50,7 @@ def get_openpype_production_icon_filepath(): def get_openpype_staging_icon_filepath(): filename = "openpype_icon_staging.png" if AYON_SERVER_ENABLED: - filename = "AYON_icon.png" + filename = "AYON_icon_staging.png" return get_resource("icons", filename) @@ -68,7 +68,10 @@ def get_openpype_splash_filepath(staging=None): staging = is_running_staging() if AYON_SERVER_ENABLED: - splash_file_name = "AYON_splash.png" + if staging: + splash_file_name = "AYON_splash_staging.png" + else: + splash_file_name = "AYON_splash.png" elif staging: splash_file_name = "openpype_splash_staging.png" else: diff --git a/openpype/resources/icons/AYON_icon_staging.png b/openpype/resources/icons/AYON_icon_staging.png new file mode 100644 index 0000000000..75dadfd56c Binary files /dev/null and b/openpype/resources/icons/AYON_icon_staging.png differ diff --git a/openpype/resources/icons/AYON_splash_staging.png b/openpype/resources/icons/AYON_splash_staging.png new file mode 100644 index 0000000000..2923413664 Binary files /dev/null and b/openpype/resources/icons/AYON_splash_staging.png differ diff --git a/openpype/settings/ayon_settings.py b/openpype/settings/ayon_settings.py index ea2b72e580..00d4a27939 100644 --- a/openpype/settings/ayon_settings.py +++ b/openpype/settings/ayon_settings.py @@ -20,6 +20,7 @@ import time import six import ayon_api +from openpype.lib.openpype_version import is_staging_enabled def _convert_color(color_value): @@ -1089,7 +1090,9 @@ class AyonSettingsCache: cls._production_settings is None or cls._production_settings.is_outdated ): - value = ayon_api.get_addons_settings(only_values=False) + variant = "staging" if is_staging_enabled() else "production" + value = ayon_api.get_addons_settings( + only_values=False, variant=variant) if cls._production_settings is None: cls._production_settings = CacheItem(value) else: