From da4ebf8eaead85285b7ae985db2788d162c82ae4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:42:31 +0100 Subject: [PATCH 1/6] use env variables to fill root values --- client/ayon_core/pipeline/anatomy/roots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/anatomy/roots.py b/client/ayon_core/pipeline/anatomy/roots.py index 2773559d49..71f842d9e0 100644 --- a/client/ayon_core/pipeline/anatomy/roots.py +++ b/client/ayon_core/pipeline/anatomy/roots.py @@ -25,7 +25,7 @@ class RootItem(FormatObject): self._log = None lowered_platform_keys = {} for key, value in root_raw_data.items(): - lowered_platform_keys[key.lower()] = value + lowered_platform_keys[key.lower()] = value.format(**os.environ) self.raw_data = lowered_platform_keys self.cleaned_data = self._clean_roots(lowered_platform_keys) self.name = name From 2615e650cb2715799af9458a5b9ef16ff8b22455 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:42:45 +0100 Subject: [PATCH 2/6] fill only platform root --- client/ayon_core/pipeline/anatomy/roots.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/client/ayon_core/pipeline/anatomy/roots.py b/client/ayon_core/pipeline/anatomy/roots.py index 71f842d9e0..1c37e82f08 100644 --- a/client/ayon_core/pipeline/anatomy/roots.py +++ b/client/ayon_core/pipeline/anatomy/roots.py @@ -23,16 +23,19 @@ class RootItem(FormatObject): def __init__(self, parent, root_raw_data, name): super(RootItem, self).__init__() self._log = None - lowered_platform_keys = {} - for key, value in root_raw_data.items(): - lowered_platform_keys[key.lower()] = value.format(**os.environ) + lowered_platform_keys = { + key.lower(): value + for key, value in root_raw_data.items() + } self.raw_data = lowered_platform_keys self.cleaned_data = self._clean_roots(lowered_platform_keys) self.name = name self.parent = parent self.available_platforms = set(lowered_platform_keys.keys()) - self.value = lowered_platform_keys.get(platform.system().lower()) + self.value = lowered_platform_keys[platform.system().lower()].format( + **os.environ + ) self.clean_value = self._clean_root(self.value) def __format__(self, *args, **kwargs): @@ -105,10 +108,10 @@ class RootItem(FormatObject): def _clean_roots(self, raw_data): """Clean all values of raw root item values.""" - cleaned = {} - for key, value in raw_data.items(): - cleaned[key] = self._clean_root(value) - return cleaned + return { + key: self._clean_root(value) + for key, value in raw_data.items() + } def path_remapper(self, path, dst_platform=None, src_platform=None): """Remap path for specific platform. From 5a6501aa0861f1eecac9d057085f3953a7416eb0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 13 Feb 2025 17:03:18 +0100 Subject: [PATCH 3/6] use 'format_map' --- client/ayon_core/pipeline/anatomy/roots.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/anatomy/roots.py b/client/ayon_core/pipeline/anatomy/roots.py index 1c37e82f08..128834dcbc 100644 --- a/client/ayon_core/pipeline/anatomy/roots.py +++ b/client/ayon_core/pipeline/anatomy/roots.py @@ -33,8 +33,10 @@ class RootItem(FormatObject): self.parent = parent self.available_platforms = set(lowered_platform_keys.keys()) - self.value = lowered_platform_keys[platform.system().lower()].format( - **os.environ + + current_platform = platform.system().lower() + self.value = lowered_platform_keys[current_platform].format_map( + os.environ ) self.clean_value = self._clean_root(self.value) From 9887b069ff1bebe2b69c757aaf4ed1df77c243d4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:44:57 +0200 Subject: [PATCH 4/6] add a warning to roots --- client/ayon_core/pipeline/anatomy/roots.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/ayon_core/pipeline/anatomy/roots.py b/client/ayon_core/pipeline/anatomy/roots.py index 128834dcbc..c7b9ff8ebc 100644 --- a/client/ayon_core/pipeline/anatomy/roots.py +++ b/client/ayon_core/pipeline/anatomy/roots.py @@ -35,6 +35,9 @@ class RootItem(FormatObject): self.available_platforms = set(lowered_platform_keys.keys()) current_platform = platform.system().lower() + # WARNING: Using environment variables in roots is not considered + # as production safe. Some features may not work as expected, for + # example USD resolver or site sync. self.value = lowered_platform_keys[current_platform].format_map( os.environ ) From 345840bb1c28cd34f433ec1465a74ed12a886560 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:06:37 +0200 Subject: [PATCH 5/6] added exception for missing environment variable --- client/ayon_core/pipeline/anatomy/__init__.py | 2 ++ .../ayon_core/pipeline/anatomy/exceptions.py | 5 +++++ client/ayon_core/pipeline/anatomy/roots.py | 22 ++++++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/pipeline/anatomy/__init__.py b/client/ayon_core/pipeline/anatomy/__init__.py index 336d09ccaa..7000f51495 100644 --- a/client/ayon_core/pipeline/anatomy/__init__.py +++ b/client/ayon_core/pipeline/anatomy/__init__.py @@ -1,5 +1,6 @@ from .exceptions import ( ProjectNotSet, + RootMissingEnv, RootCombinationError, TemplateMissingKey, AnatomyTemplateUnsolved, @@ -9,6 +10,7 @@ from .anatomy import Anatomy __all__ = ( "ProjectNotSet", + "RootMissingEnv", "RootCombinationError", "TemplateMissingKey", "AnatomyTemplateUnsolved", diff --git a/client/ayon_core/pipeline/anatomy/exceptions.py b/client/ayon_core/pipeline/anatomy/exceptions.py index 39f116baf0..24df0e3046 100644 --- a/client/ayon_core/pipeline/anatomy/exceptions.py +++ b/client/ayon_core/pipeline/anatomy/exceptions.py @@ -5,6 +5,11 @@ class ProjectNotSet(Exception): """Exception raised when is created Anatomy without project name.""" +class RootMissingEnv(KeyError): + """Raised when root requires environment variables which is not filled.""" + pass + + class RootCombinationError(Exception): """This exception is raised when templates has combined root types.""" diff --git a/client/ayon_core/pipeline/anatomy/roots.py b/client/ayon_core/pipeline/anatomy/roots.py index c7b9ff8ebc..bd09a9fe51 100644 --- a/client/ayon_core/pipeline/anatomy/roots.py +++ b/client/ayon_core/pipeline/anatomy/roots.py @@ -2,9 +2,11 @@ import os import platform import numbers -from ayon_core.lib import Logger +from ayon_core.lib import Logger, StringTemplate from ayon_core.lib.path_templates import FormatObject +from .exceptions import RootMissingEnv + class RootItem(FormatObject): """Represents one item or roots. @@ -21,7 +23,7 @@ class RootItem(FormatObject): multi root setup otherwise None value is expected. """ def __init__(self, parent, root_raw_data, name): - super(RootItem, self).__init__() + super().__init__() self._log = None lowered_platform_keys = { key.lower(): value @@ -38,9 +40,19 @@ class RootItem(FormatObject): # WARNING: Using environment variables in roots is not considered # as production safe. Some features may not work as expected, for # example USD resolver or site sync. - self.value = lowered_platform_keys[current_platform].format_map( - os.environ - ) + try: + self.value = lowered_platform_keys[current_platform].format_map( + os.environ + ) + except KeyError: + result = StringTemplate(self.value).format(os.environ.copy()) + is_are = "is" if len(result.missing_keys) == 1 else "are" + missing_keys = ", ".join(result.missing_keys) + raise RootMissingEnv( + f"Root \"{name}\" requires environment variable/s" + f" {missing_keys} which {is_are} not available." + ) + self.clean_value = self._clean_root(self.value) def __format__(self, *args, **kwargs): From 9986e7def97e620dc27b6eb69417f1a5ab1e5483 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:06:48 +0200 Subject: [PATCH 6/6] capture exception in pre launch hook --- client/ayon_core/hooks/pre_global_host_data.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/hooks/pre_global_host_data.py b/client/ayon_core/hooks/pre_global_host_data.py index 12da6f12f8..23f725901c 100644 --- a/client/ayon_core/hooks/pre_global_host_data.py +++ b/client/ayon_core/hooks/pre_global_host_data.py @@ -1,12 +1,15 @@ from ayon_api import get_project, get_folder_by_path, get_task_by_name +from ayon_core.pipeline import Anatomy +from ayon_core.pipeline.anatomy import RootMissingEnv + from ayon_applications import PreLaunchHook +from ayon_applications.exceptions import ApplicationLaunchFailed from ayon_applications.utils import ( EnvironmentPrepData, prepare_app_environments, prepare_context_environments ) -from ayon_core.pipeline import Anatomy class GlobalHostDataHook(PreLaunchHook): @@ -67,9 +70,12 @@ class GlobalHostDataHook(PreLaunchHook): self.data["project_entity"] = project_entity # Anatomy - self.data["anatomy"] = Anatomy( - project_name, project_entity=project_entity - ) + try: + self.data["anatomy"] = Anatomy( + project_name, project_entity=project_entity + ) + except RootMissingEnv as exc: + raise ApplicationLaunchFailed(str(exc)) folder_path = self.data.get("folder_path") if not folder_path: