From 27793cef1f93f87e75bd1652929f8c4da5deccc0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 16:06:57 +0100 Subject: [PATCH 1/9] added helper object to handle selection in launcher --- client/ayon_core/pipeline/actions.py | 237 +++++++++++++++++- .../tools/launcher/models/actions.py | 62 ++--- 2 files changed, 248 insertions(+), 51 deletions(-) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index 8e0ce7e583..d6e589c0ef 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -1,4 +1,7 @@ import logging + +import ayon_api + from ayon_core.pipeline.plugin_discover import ( discover, register_plugin, @@ -10,6 +13,224 @@ from ayon_core.pipeline.plugin_discover import ( from .load.utils import get_representation_path_from_context +class LauncherActionSelection: + """Object helper to pass selection to actions. + + Object support backwards compatibility for 'session' from OpenPype where + environment variable keys were used to define selection. + + Args: + project_name (str): Selected project name. + folder_id (str): Selected folder id. + task_id (str): Selected task id. + folder_path (Optional[str]): Selected folder path. + task_name (Optional[str]): Selected task name. + project_entity (Optional[dict[str, Any]]): Project entity. + folder_entity (Optional[dict[str, Any]]): Folder entity. + task_entity (Optional[dict[str, Any]]): Task entity. + + """ + def __init__( + self, + project_name, + folder_id, + task_id, + folder_path=None, + task_name=None, + project_entity=None, + folder_entity=None, + task_entity=None + ): + self._project_name = project_name + self._folder_id = folder_id + self._task_id = task_id + + self._folder_path = folder_path + self._task_name = task_name + + self._project_entity = project_entity + self._folder_entity = folder_entity + self._task_entity = task_entity + + def __getitem__(self, key): + if key in {"project_name", "AYON_PROJECT_NAME", "AVALON_PROJECT"}: + return self.project_name + if key == {"folder_path", "AYON_FOLDER_PATH", "AVALON_ASSET"}: + return self.folder_path + if key == {"task_name", "AYON_TASK_NAME", "AVALON_TASK"}: + return self.task_name + if key == "folder_id": + return self.folder_id + if key == "task_id": + return self.task_id + if key == "project_entity": + return self.project_entity + if key == "folder_entity": + return self.folder_entity + if key == "task_entity": + return self.task_entity + raise KeyError(f"Key: {key} not found") + + def __contains__(self, key): + # Fake missing keys check for backwards compatibility + if key in { + "AYON_PROJECT_NAME", + "AVALON_PROJECT", + "project_entity", + }: + return self._project_name is not None + if key in { + "AYON_FOLDER_PATH", + "folder_id", + "folder_path", + "folder_entity", + "AVALON_ASSET", + }: + return self._folder_id is not None + if key in { + "AYON_TASK_NAME", + "task_id", + "task_name", + "task_entity", + "AVALON_TASK", + }: + return self._task_id is not None + return False + + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def get_project_name(self): + """Selected project name. + + Returns: + Union[str, None]: Selected project name. + + """ + return self._project_name + + def get_folder_id(self): + """Selected folder id. + + Returns: + Union[str, None]: Selected folder id. + + """ + return self._folder_id + + def get_folder_path(self): + """Selected folder path. + + Returns: + Union[str, None]: Selected folder path. + + """ + if self._folder_id is None: + return None + if self._folder_path is None: + self._folder_path = self.folder_entity["path"] + return self._folder_path + + def get_task_id(self): + """Selected task id. + + Returns: + Union[str, None]: Selected task id. + + """ + return self._task_id + + def get_task_name(self): + """Selected task name. + + Returns: + Union[str, None]: Selected task name. + + """ + if self._task_id is None: + return None + if self._task_name is None: + self._task_name = self.task_entity["name"] + return self._task_name + + def get_project_entity(self): + """Project entity for the selection. + + Returns: + Union[dict[str, Any], None]: Project entity. + + """ + if self._project_name is None: + return None + if self._project_entity is None: + self._project_entity = ayon_api.get_project(self._project_name) + return self._project_entity + + def get_folder_entity(self): + """Folder entity for the selection. + + Returns: + Union[dict[str, Any], None]: Folder entity. + + """ + if self._project_name is None or self._folder_id is None: + return None + if self._folder_entity is None: + self._folder_entity = ayon_api.get_folder_by_id( + self._project_name, self._folder_id + ) + return self._folder_entity + + def get_task_entity(self): + """Task entity for the selection. + + Returns: + Union[dict[str, Any], None]: Task entity. + + """ + if ( + self._project_name is None + or self._task_id is None + ): + return None + if self._task_entity is None: + self._task_entity = ayon_api.get_task_by_id( + self._project_name, self._task_id + ) + return self._task_entity + + @property + def is_project_selected(self): + """Return whether a project is selected. + + Returns: + bool: Whether a project is selected. + + """ + return self._project_name is not None + + @property + def is_folder_selected(self): + return self._folder_id is not None + + @property + def is_task_selected(self): + return self._task_id is not None + + project_name = property(get_project_name) + folder_id = property(get_folder_id) + task_id = property(get_task_id) + folder_path = property(get_folder_path) + task_name = property(get_task_name) + + project_entity = property(get_project_entity) + folder_entity = property(get_folder_entity) + task_entity = property(get_task_entity) + + class LauncherAction(object): """A custom action available""" name = None @@ -21,17 +242,23 @@ class LauncherAction(object): log = logging.getLogger("LauncherAction") log.propagate = True - def is_compatible(self, session): + def is_compatible(self, selection): """Return whether the class is compatible with the Session. Args: - session (dict[str, Union[str, None]]): Session data with - AYON_PROJECT_NAME, AYON_FOLDER_PATH and AYON_TASK_NAME. - """ + selection (LauncherActionSelection): Data with selection. + """ return True - def process(self, session, **kwargs): + def process(self, selection, **kwargs): + """Process the action. + + Args: + selection (LauncherActionSelection): Data with selection. + **kwargs: Additional arguments. + + """ pass diff --git a/client/ayon_core/tools/launcher/models/actions.py b/client/ayon_core/tools/launcher/models/actions.py index 97943e6ad7..6da34151b6 100644 --- a/client/ayon_core/tools/launcher/models/actions.py +++ b/client/ayon_core/tools/launcher/models/actions.py @@ -5,6 +5,7 @@ from ayon_core.lib import Logger, AYONSettingsRegistry from ayon_core.pipeline.actions import ( discover_launcher_actions, LauncherAction, + LauncherActionSelection, ) from ayon_core.pipeline.workfile import should_use_last_workfile_on_launch @@ -69,11 +70,6 @@ class ApplicationAction(LauncherAction): project_entities = {} _log = None - required_session_keys = ( - "AYON_PROJECT_NAME", - "AYON_FOLDER_PATH", - "AYON_TASK_NAME" - ) @property def log(self): @@ -81,18 +77,16 @@ class ApplicationAction(LauncherAction): self._log = Logger.get_logger(self.__class__.__name__) return self._log - def is_compatible(self, session): - for key in self.required_session_keys: - if not session.get(key): - return False + def is_compatible(self, selection): + if not selection.is_task_selected: + return False - project_name = session["AYON_PROJECT_NAME"] - project_entity = self.project_entities[project_name] + project_entity = self.project_entities[selection.project_name] apps = project_entity["attrib"].get("applications") if not apps or self.application.full_name not in apps: return False - project_settings = self.project_settings[project_name] + project_settings = self.project_settings[selection.project_name] only_available = project_settings["applications"]["only_available"] if only_available and not self.application.find_executable(): return False @@ -112,7 +106,7 @@ class ApplicationAction(LauncherAction): dialog.setDetailedText(details) dialog.exec_() - def process(self, session, **kwargs): + def process(self, selection, **kwargs): """Process the full Application action""" from ayon_core.lib import ( @@ -120,14 +114,11 @@ class ApplicationAction(LauncherAction): ApplicationLaunchFailed, ) - project_name = session["AYON_PROJECT_NAME"] - folder_path = session["AYON_FOLDER_PATH"] - task_name = session["AYON_TASK_NAME"] try: self.application.launch( - project_name=project_name, - folder_path=folder_path, - task_name=task_name, + project_name=selection.project_name, + folder_path=selection.folder_path, + task_name=selection.task_name, **self.data ) @@ -335,11 +326,11 @@ class ActionsModel: """ not_open_workfile_actions = self._get_no_last_workfile_for_context( project_name, folder_id, task_id) - session = self._prepare_session(project_name, folder_id, task_id) + selection = self._prepare_selection(project_name, folder_id, task_id) output = [] action_items = self._get_action_items(project_name) for identifier, action in self._get_action_objects().items(): - if not action.is_compatible(session): + if not action.is_compatible(selection): continue action_item = action_items[identifier] @@ -374,7 +365,7 @@ class ActionsModel: ) def trigger_action(self, project_name, folder_id, task_id, identifier): - session = self._prepare_session(project_name, folder_id, task_id) + selection = self._prepare_selection(project_name, folder_id, task_id) failed = False error_message = None action_label = identifier @@ -403,7 +394,7 @@ class ActionsModel: ) action.data["start_last_workfile"] = start_last_workfile - action.process(session) + action.process(selection) except Exception as exc: self.log.warning("Action trigger failed.", exc_info=True) failed = True @@ -440,29 +431,8 @@ class ActionsModel: .get(task_id, {}) ) - def _prepare_session(self, project_name, folder_id, task_id): - folder_path = None - if folder_id: - folder = self._controller.get_folder_entity( - project_name, folder_id) - if folder: - folder_path = folder["path"] - - task_name = None - if task_id: - task = self._controller.get_task_entity(project_name, task_id) - if task: - task_name = task["name"] - - return { - "AYON_PROJECT_NAME": project_name, - "AYON_FOLDER_PATH": folder_path, - "AYON_TASK_NAME": task_name, - # Deprecated - kept for backwards compatibility - "AVALON_PROJECT": project_name, - "AVALON_ASSET": folder_path, - "AVALON_TASK": task_name, - } + def _prepare_selection(self, project_name, folder_id, task_id): + return LauncherActionSelection(project_name, folder_id, task_id) def _get_discovered_action_classes(self): if self._discovered_actions is None: From 93b9541268e0885052126ab647441db56be19a14 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 16:07:13 +0100 Subject: [PATCH 2/9] use new options of selection object --- .../launcher_actions/ClockifyStart.py | 14 ++++----- .../clockify/launcher_actions/ClockifySync.py | 12 ++++---- .../plugins/actions/open_file_explorer.py | 29 +++++++++---------- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/client/ayon_core/modules/clockify/launcher_actions/ClockifyStart.py b/client/ayon_core/modules/clockify/launcher_actions/ClockifyStart.py index 61c5eac2f5..8381c7d73e 100644 --- a/client/ayon_core/modules/clockify/launcher_actions/ClockifyStart.py +++ b/client/ayon_core/modules/clockify/launcher_actions/ClockifyStart.py @@ -11,19 +11,17 @@ class ClockifyStart(LauncherAction): order = 500 clockify_api = ClockifyAPI() - def is_compatible(self, session): + def is_compatible(self, selection): """Return whether the action is compatible with the session""" - if "AYON_TASK_NAME" in session: - return True - return False + return selection.is_task_selected - def process(self, session, **kwargs): + def process(self, selection, **kwargs): self.clockify_api.set_api() user_id = self.clockify_api.user_id workspace_id = self.clockify_api.workspace_id - project_name = session["AYON_PROJECT_NAME"] - folder_path = session["AYON_FOLDER_PATH"] - task_name = session["AYON_TASK_NAME"] + project_name = selection.project_name + folder_path = selection.folder_path + task_name = selection.task_name description = "/".join([folder_path.lstrip("/"), task_name]) # fetch folder entity diff --git a/client/ayon_core/modules/clockify/launcher_actions/ClockifySync.py b/client/ayon_core/modules/clockify/launcher_actions/ClockifySync.py index 72187c6d28..5388f47c98 100644 --- a/client/ayon_core/modules/clockify/launcher_actions/ClockifySync.py +++ b/client/ayon_core/modules/clockify/launcher_actions/ClockifySync.py @@ -19,15 +19,18 @@ class ClockifySync(LauncherAction): order = 500 clockify_api = ClockifyAPI() - def is_compatible(self, session): + def is_compatible(self, selection): """Check if there's some projects to sync""" + if selection.is_project_selected: + return True + try: next(ayon_api.get_projects()) return True except StopIteration: return False - def process(self, session, **kwargs): + def process(self, selection, **kwargs): self.clockify_api.set_api() workspace_id = self.clockify_api.workspace_id user_id = self.clockify_api.user_id @@ -37,10 +40,9 @@ class ClockifySync(LauncherAction): raise ClockifyPermissionsCheckFailed( "Current CLockify user is missing permissions for this action!" ) - project_name = session.get("AYON_PROJECT_NAME") or "" - if project_name.strip(): - projects_to_sync = [ayon_api.get_project(project_name)] + if selection.is_project_selected: + projects_to_sync = [selection.project_entity] else: projects_to_sync = ayon_api.get_projects() diff --git a/client/ayon_core/plugins/actions/open_file_explorer.py b/client/ayon_core/plugins/actions/open_file_explorer.py index 69375a7859..6a456c75c1 100644 --- a/client/ayon_core/plugins/actions/open_file_explorer.py +++ b/client/ayon_core/plugins/actions/open_file_explorer.py @@ -18,18 +18,14 @@ class OpenTaskPath(LauncherAction): icon = "folder-open" order = 500 - def is_compatible(self, session): + def is_compatible(self, selection): """Return whether the action is compatible with the session""" - return bool(session.get("AYON_FOLDER_PATH")) + return selection.is_folder_selected - def process(self, session, **kwargs): + def process(self, selection, **kwargs): from qtpy import QtCore, QtWidgets - project_name = session["AYON_PROJECT_NAME"] - folder_path = session["AYON_FOLDER_PATH"] - task_name = session.get("AYON_TASK_NAME", None) - - path = self._get_workdir(project_name, folder_path, task_name) + path = self._get_workdir(selection) if not path: return @@ -60,16 +56,17 @@ class OpenTaskPath(LauncherAction): path = path.split(field, 1)[0] return path - def _get_workdir(self, project_name, folder_path, task_name): - project_entity = ayon_api.get_project(project_name) - folder_entity = ayon_api.get_folder_by_path(project_name, folder_path) - task_entity = ayon_api.get_task_by_name( - project_name, folder_entity["id"], task_name + def _get_workdir(self, selection): + data = get_template_data( + selection.project_entity, + selection.folder_entity, + selection.task_entity ) - data = get_template_data(project_entity, folder_entity, task_entity) - - anatomy = Anatomy(project_name) + anatomy = Anatomy( + selection.project_name, + project_entity=selection.project_entity + ) workdir = anatomy.get_template_item( "work", "default", "folder" ).format(data) From b6269b176516426a53bb227d8a390464623ec5a0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 28 Mar 2024 16:34:10 +0100 Subject: [PATCH 3/9] Add missing docstrings. Co-authored-by: Roy Nieterau --- client/ayon_core/pipeline/actions.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index d6e589c0ef..52d68800d1 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -214,10 +214,22 @@ class LauncherActionSelection: @property def is_folder_selected(self): + """Return whether a folder is selected. + + Returns: + bool: Whether a folder is selected. + + """ return self._folder_id is not None @property def is_task_selected(self): + """Return whether a task is selected. + + Returns: + bool: Whether a task is selected. + + """ return self._task_id is not None project_name = property(get_project_name) From 24d6280ae68ebf1c3168635f472ed76fab21e882 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 28 Mar 2024 16:36:21 +0100 Subject: [PATCH 4/9] Houdini: Fix creating instances from tab menu --- client/ayon_core/hosts/houdini/api/creator_node_shelves.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/houdini/api/creator_node_shelves.py b/client/ayon_core/hosts/houdini/api/creator_node_shelves.py index 6e48cb375b..72c157f187 100644 --- a/client/ayon_core/hosts/houdini/api/creator_node_shelves.py +++ b/client/ayon_core/hosts/houdini/api/creator_node_shelves.py @@ -91,7 +91,7 @@ def create_interactive(creator_identifier, **kwargs): pane = stateutils.activePane(kwargs) if isinstance(pane, hou.NetworkEditor): pwd = pane.pwd() - project_name = context.get_current_project_name(), + project_name = context.get_current_project_name() folder_path = context.get_current_folder_path() task_name = context.get_current_task_name() folder_entity = ayon_api.get_folder_by_path( From 66f3b4cbf6573d87f0dccd0a2f427aaf6f6cfef0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 16:39:42 +0100 Subject: [PATCH 5/9] keep dict like access only for backwards compatible keys --- client/ayon_core/pipeline/actions.py | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index 52d68800d1..9ccc82e4a9 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -53,22 +53,12 @@ class LauncherActionSelection: self._task_entity = task_entity def __getitem__(self, key): - if key in {"project_name", "AYON_PROJECT_NAME", "AVALON_PROJECT"}: + if key in {"AYON_PROJECT_NAME", "AVALON_PROJECT"}: return self.project_name - if key == {"folder_path", "AYON_FOLDER_PATH", "AVALON_ASSET"}: + if key == {"AYON_FOLDER_PATH", "AVALON_ASSET"}: return self.folder_path - if key == {"task_name", "AYON_TASK_NAME", "AVALON_TASK"}: + if key == {"AYON_TASK_NAME", "AVALON_TASK"}: return self.task_name - if key == "folder_id": - return self.folder_id - if key == "task_id": - return self.task_id - if key == "project_entity": - return self.project_entity - if key == "folder_entity": - return self.folder_entity - if key == "task_entity": - return self.task_entity raise KeyError(f"Key: {key} not found") def __contains__(self, key): @@ -76,22 +66,15 @@ class LauncherActionSelection: if key in { "AYON_PROJECT_NAME", "AVALON_PROJECT", - "project_entity", }: return self._project_name is not None if key in { "AYON_FOLDER_PATH", - "folder_id", - "folder_path", - "folder_entity", "AVALON_ASSET", }: return self._folder_id is not None if key in { "AYON_TASK_NAME", - "task_id", - "task_name", - "task_entity", "AVALON_TASK", }: return self._task_id is not None From 8fab7139694d74ab958f5eefeb9426e8d8576c23 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 16:43:42 +0100 Subject: [PATCH 6/9] added deprecation warnings --- client/ayon_core/pipeline/actions.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index 9ccc82e4a9..9b5234d811 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -1,4 +1,5 @@ import logging +import warnings import ayon_api @@ -53,6 +54,14 @@ class LauncherActionSelection: self._task_entity = task_entity def __getitem__(self, key): + warnings.warn( + ( + "Using deprecated access to selection data. Please use" + " attributes and methods" + " defined by 'LauncherActionSelection'." + ), + category=DeprecationWarning + ) if key in {"AYON_PROJECT_NAME", "AVALON_PROJECT"}: return self.project_name if key == {"AYON_FOLDER_PATH", "AVALON_ASSET"}: @@ -62,6 +71,14 @@ class LauncherActionSelection: raise KeyError(f"Key: {key} not found") def __contains__(self, key): + warnings.warn( + ( + "Using deprecated access to selection data. Please use" + " attributes and methods" + " defined by 'LauncherActionSelection'." + ), + category=DeprecationWarning + ) # Fake missing keys check for backwards compatibility if key in { "AYON_PROJECT_NAME", @@ -81,6 +98,14 @@ class LauncherActionSelection: return False def get(self, key, default=None): + warnings.warn( + ( + "Using deprecated access to selection data. Please use" + " attributes and methods" + " defined by 'LauncherActionSelection'." + ), + category=DeprecationWarning + ) try: return self[key] except KeyError: From b75a3bca4f1dc0d159e265066a73a481f757997c Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 16:57:10 +0100 Subject: [PATCH 7/9] fix in conditions --- client/ayon_core/pipeline/actions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index 9b5234d811..0d2a05f7cd 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -64,9 +64,9 @@ class LauncherActionSelection: ) if key in {"AYON_PROJECT_NAME", "AVALON_PROJECT"}: return self.project_name - if key == {"AYON_FOLDER_PATH", "AVALON_ASSET"}: + if key in {"AYON_FOLDER_PATH", "AVALON_ASSET"}: return self.folder_path - if key == {"AYON_TASK_NAME", "AVALON_TASK"}: + if key in {"AYON_TASK_NAME", "AVALON_TASK"}: return self.task_name raise KeyError(f"Key: {key} not found") From 5b5ab5df8b93e07ce19dc5e5c3654bcb184c57cf Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 17:00:24 +0100 Subject: [PATCH 8/9] implemented rest of dict-like methods --- client/ayon_core/pipeline/actions.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index 0d2a05f7cd..a2eb8e7eee 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -70,6 +70,10 @@ class LauncherActionSelection: return self.task_name raise KeyError(f"Key: {key} not found") + def __iter__(self): + for key in self.keys(): + yield key + def __contains__(self, key): warnings.warn( ( @@ -111,6 +115,23 @@ class LauncherActionSelection: except KeyError: return default + def items(self): + for key, value in ( + ("AYON_PROJECT_NAME", self.project_name), + ("AYON_FOLDER_PATH", self.folder_path), + ("AYON_TASK_NAME", self.task_name), + ): + if value is not None: + yield (key, value) + + def keys(self): + for key, _ in self.items(): + yield key + + def values(self): + for _, value in self.items(): + yield value + def get_project_name(self): """Selected project name. From 2b149b50ee3a6e019b4cdeb75c446a460af60a54 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 28 Mar 2024 17:28:16 +0100 Subject: [PATCH 9/9] added deprecation to method docstrings --- client/ayon_core/pipeline/actions.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/client/ayon_core/pipeline/actions.py b/client/ayon_core/pipeline/actions.py index a2eb8e7eee..eae2fc94b5 100644 --- a/client/ayon_core/pipeline/actions.py +++ b/client/ayon_core/pipeline/actions.py @@ -102,6 +102,12 @@ class LauncherActionSelection: return False def get(self, key, default=None): + """ + + Deprecated: + Added for backwards compatibility with older actions. + + """ warnings.warn( ( "Using deprecated access to selection data. Please use" @@ -116,6 +122,12 @@ class LauncherActionSelection: return default def items(self): + """ + + Deprecated: + Added for backwards compatibility with older actions. + + """ for key, value in ( ("AYON_PROJECT_NAME", self.project_name), ("AYON_FOLDER_PATH", self.folder_path), @@ -125,10 +137,22 @@ class LauncherActionSelection: yield (key, value) def keys(self): + """ + + Deprecated: + Added for backwards compatibility with older actions. + + """ for key, _ in self.items(): yield key def values(self): + """ + + Deprecated: + Added for backwards compatibility with older actions. + + """ for _, value in self.items(): yield value