From 37b732454da1340bdea91fcf9ba7f0aa2ba9bbc5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 17 Sep 2026 22:08:48 +0200 Subject: [PATCH 1/3] Query folders with `get_rest_folders` instead of `get_folders_hierarchy` for general speed improvement. Performance for 10,328 folders, local server, 10 repeats - OLD (`get_folders_hierarchy` full call) mean: 796.5 ms | median: 629.5 ms - NEW (`get_rest_folders` full call) mean: 235.8 ms | median: 181.6 ms - NEW + `__slots__` (full call) mean: 222.5 ms | median: 186.6 ms The slots call is a neglible ~4-6% faster in processing, however it reduces its memory usage by +/-46% and since we do keep these in cache it's a nice bonus (even though we're talking only 403 KiB saved for this dataset) --- .../tools/common_models/hierarchy.py | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/client/ayon_core/tools/common_models/hierarchy.py b/client/ayon_core/tools/common_models/hierarchy.py index 1f204ac4222..fb8bfde4e56 100644 --- a/client/ayon_core/tools/common_models/hierarchy.py +++ b/client/ayon_core/tools/common_models/hierarchy.py @@ -1,7 +1,6 @@ from __future__ import annotations from abc import ABC, abstractmethod -import collections import contextlib from dataclasses import dataclass import time @@ -43,6 +42,10 @@ class FolderItem: label (str): Folder label. """ + # TODO: Use `@dataclass(slots=True)' when we drop Python 3.9 support. + __slots__ = ( + "entity_id", "parent_id", "name", "path", "folder_type", "label", + ) entity_id: str parent_id: str | None name: str @@ -80,25 +83,25 @@ def from_data(cls, data: dict[str, str | None]) -> FolderItem: return cls(**data) @classmethod - def from_hierarchy_item(cls, item: dict[str, Any]) -> FolderItem: - """Creates folder item from hierarchy item. + def from_rest_data(cls, data: dict[str, Any]) -> FolderItem: + """Creates folder item from 'get_rest_folders' flat item. + + Unlike the GraphQl based entity data, the REST flat folder path + is not prefixed with a leading '/', so it is added here to keep + the same path format as other constructors. Args: - item (dict[str, Any]): Hierarchy item. + data (dict[str, Any]): Flat folder item from REST endpoint. """ - name = item["name"] - path_parts = list(item["parents"]) - path_parts.append(name) - path_parts.insert(0, "") - path = "/".join(path_parts) - return FolderItem( - entity_id=item["id"], - parent_id=item["parentId"], + name = data["name"] + return cls( + entity_id=data["id"], + parent_id=data["parentId"], name=name, - path=path, - folder_type=item["folderType"], - label=item["label"] or name, + path=f"/{data['path']}", + folder_type=data["folderType"], + label=data["label"] or name, ) @classmethod @@ -646,16 +649,11 @@ def _refresh_folders_cache( self._folders_items[project_name].update_data(folder_items) def _query_folders(self, project_name: str) -> dict[str, FolderItem]: - hierarchy = ayon_api.get_folders_hierarchy(project_name) - - folder_items = {} - hierachy_queue = collections.deque(hierarchy["hierarchy"]) - while hierachy_queue: - item = hierachy_queue.popleft() - folder_item = FolderItem.from_hierarchy_item(item) - folder_items[folder_item.entity_id] = folder_item - hierachy_queue.extend(item["children"] or []) - return folder_items + folders = ayon_api.get_rest_folders(project_name, include_attrib=False) + return { + folder["id"]: FolderItem.from_rest_data(folder) + for folder in folders + } def _query_folder_entities( self, project_name: str, folder_ids: set[str] From ba358feff52b05e7b703818934a5fbeb1a1e172c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 17 Sep 2026 22:11:06 +0200 Subject: [PATCH 2/3] Simplify docstring --- client/ayon_core/tools/common_models/hierarchy.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/ayon_core/tools/common_models/hierarchy.py b/client/ayon_core/tools/common_models/hierarchy.py index fb8bfde4e56..5f1698d498e 100644 --- a/client/ayon_core/tools/common_models/hierarchy.py +++ b/client/ayon_core/tools/common_models/hierarchy.py @@ -86,10 +86,6 @@ def from_data(cls, data: dict[str, str | None]) -> FolderItem: def from_rest_data(cls, data: dict[str, Any]) -> FolderItem: """Creates folder item from 'get_rest_folders' flat item. - Unlike the GraphQl based entity data, the REST flat folder path - is not prefixed with a leading '/', so it is added here to keep - the same path format as other constructors. - Args: data (dict[str, Any]): Flat folder item from REST endpoint. From 38522ea7779d85f3b52bc45dc1cd0fba0cc153a4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 17 Sep 2026 23:53:24 +0200 Subject: [PATCH 3/3] Fix comment formatting in hierarchy.py Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- client/ayon_core/tools/common_models/hierarchy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/tools/common_models/hierarchy.py b/client/ayon_core/tools/common_models/hierarchy.py index 5f1698d498e..39582dab094 100644 --- a/client/ayon_core/tools/common_models/hierarchy.py +++ b/client/ayon_core/tools/common_models/hierarchy.py @@ -42,7 +42,7 @@ class FolderItem: label (str): Folder label. """ - # TODO: Use `@dataclass(slots=True)' when we drop Python 3.9 support. + # TODO: Use `@dataclass(slots=True)` when we drop Python 3.9 support. __slots__ = ( "entity_id", "parent_id", "name", "path", "folder_type", "label", )