From 4b3d6bdc0d8cac0d6f9c9680436af2d2e1b14f81 Mon Sep 17 00:00:00 2001 From: "robin@ynput.io" Date: Tue, 12 Nov 2024 16:59:36 -0500 Subject: [PATCH 1/8] Allow CSV ingest to create new shots. --- .../plugins/create/create_csv_ingest.py | 93 +++++++++++++++++-- 1 file changed, 87 insertions(+), 6 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index 55e77ca..068b041 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -181,6 +181,8 @@ def __init__( self.variant = variant self.product_type = product_type self.repre_items: List[RepreItem] = [] + self.has_promised_context = False + self.parents = None self._unique_name = None self._pre_product_name = None @@ -388,6 +390,54 @@ def _resolve_repre_path( return filepath + @staticmethod + def _validate_parents(project_name: str, product_item: ProductItem) -> list: + """ Ensure parent exists for provided product_item.folder_path + + Args: + project_name (str): The project name. + product_item (ProductItem): The product item to inspect. + + Returns: + list. The parent list if any + + Raise: + ValueError: When provided folder_path parent do not exist. + """ + parent_folder_path, folder_name = product_item.folder_path.rsplit("/", 1) + if not parent_folder_path: + return [] + + folder_data = ayon_api.get_folder_by_path( + project_name, + parent_folder_path, + fields=("folderType",) + ) + + if folder_data is None: + raise ValueError(f"Unknown parent folder {parent_folder_path}") + + parent_data = [] + inspected = [] + + for key in parent_folder_path.split("/"): + if not key: + continue + + inspected.append(key) + folder_data = ayon_api.get_folder_by_path( + project_name, + f"/{'/'.join(inspected)}", + fields=("folderType",) + ) + parent_data.append({ + "folder_type": folder_data["folderType"], + "entity_name": key + }) + + return parent_data + + def _get_data_from_csv( self, csv_dir: str, filename: str ) -> Dict[str, ProductItem]: @@ -458,12 +508,6 @@ def _get_data_from_csv( ) } missing_paths: Set[str] = folder_paths - set(folder_ids_by_path.keys()) - if missing_paths: - ending = "" if len(missing_paths) == 1 else "s" - joined_paths = "\n".join(sorted(missing_paths)) - raise CreatorError( - f"Folder{ending} not found.\n{joined_paths}" - ) task_names: Set[str] = { product_item.task_name @@ -482,6 +526,22 @@ def _get_data_from_csv( missing_tasks: Set[str] = set() for product_item in product_items_by_name.values(): folder_path = product_item.folder_path + + if folder_path in missing_paths: + product_item.has_promised_context = True + product_item.task_type = None + try: + product_item.parents = self._validate_parents( + project_name, + product_item + ) + except ValueError: + raise CreatorError( + f"Parent context must exists for new shots: {folder_path}" + ) + + continue + task_name = product_item.task_name folder_id = folder_ids_by_path[folder_path] task_entities = task_entities_by_folder_id[folder_id] @@ -835,6 +895,23 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): "prepared_data_for_repres": [] } + if product_item.has_promised_context: + hierarchy, _ = folder_path.rsplit("/",1) + families.append("csv_ingest_shot") + instance_data.update( + { + "newHierarchyIntegration": True, + "hierarchy": hierarchy, + "parents": product_item.parents + } + ) + # TODO create new task from provided task name +# if product_item.task_name: +# instance_data["tasks"] = { +# "name": product_item.task_name, +# "type": "Generic" +# } + # create new instance new_instance: CreatedInstance = CreatedInstance( product_item.product_type, @@ -843,6 +920,10 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): self ) self._prepare_representations(product_item, new_instance) + + if product_item.has_promised_context: + new_instance.transient_data["has_promised_context"] = True + instances.append(new_instance) return instances From 63413da5c0827d86f768280fea5abff6f8d1576e Mon Sep 17 00:00:00 2001 From: Robin De Lillo Date: Wed, 13 Nov 2024 14:40:05 -0500 Subject: [PATCH 2/8] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Co-authored-by: Kayla Man <64118225+moonyuet@users.noreply.github.com> Co-authored-by: Jakub Ježek --- .../plugins/create/create_csv_ingest.py | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index 068b041..b3db9f6 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -404,37 +404,39 @@ def _validate_parents(project_name: str, product_item: ProductItem) -> list: Raise: ValueError: When provided folder_path parent do not exist. """ - parent_folder_path, folder_name = product_item.folder_path.rsplit("/", 1) - if not parent_folder_path: + parent_folder_names = product_item.folder_path.lstrip("/").split("/") + # Rename name of folder itself + parent_folder_names.pop(-1) + if not parent_folder_names: return [] - folder_data = ayon_api.get_folder_by_path( - project_name, - parent_folder_path, - fields=("folderType",) - ) - - if folder_data is None: - raise ValueError(f"Unknown parent folder {parent_folder_path}") + parent_paths = [] + parent_path = "" + for name in parent_folder_names: + path = f"{parent_path}/{name}" + parent_paths.append(path) + parent_path = path - parent_data = [] - inspected = [] - - for key in parent_folder_path.split("/"): - if not key: - continue - - inspected.append(key) - folder_data = ayon_api.get_folder_by_path( + folders_by_path = { + folder["path"]: folder + for folder in ayon_api.get_folders( project_name, - f"/{'/'.join(inspected)}", - fields=("folderType",) + folder_paths=parent_paths, + fields={"folderType", "path"} ) + } + parent_data = [] + for path in parent_paths: + folder_entity = folders_by_path.get(path) + if not folder_entity: + # TODO This should be some artist friendy error + # raising 'CreatorError' + raise ValueError(f"Unknown parent folder {path}") + name = path.rsplit("/", 1)[-1] parent_data.append({ - "folder_type": folder_data["folderType"], - "entity_name": key + "folder_type": folder_entity["folderType"], + "entity_name": name }) - return parent_data @@ -896,7 +898,7 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): } if product_item.has_promised_context: - hierarchy, _ = folder_path.rsplit("/",1) + hierarchy, _ = folder_path.rsplit("/", 1) families.append("csv_ingest_shot") instance_data.update( { @@ -906,11 +908,14 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): } ) # TODO create new task from provided task name -# if product_item.task_name: -# instance_data["tasks"] = { -# "name": product_item.task_name, -# "type": "Generic" -# } + if product_item.task_name: + tasks = instance_data.setdefault("tasks", []) + tasks.append( + { + "name": product_item.task_name, + "type": "Generic" + } + ) # create new instance new_instance: CreatedInstance = CreatedInstance( From 303efed0c1807a3013d4caefc566f4f49d01b9ff Mon Sep 17 00:00:00 2001 From: "robin@ynput.io" Date: Wed, 13 Nov 2024 17:13:19 -0500 Subject: [PATCH 3/8] Add plugin settings for traypublishr CSV ingest --- .../plugins/create/create_csv_ingest.py | 48 +++++++++++++------ server/settings/creator_plugins.py | 38 ++++++++++++++- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index b3db9f6..4c0e065 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -251,6 +251,7 @@ class IngestCSV(TrayPublishCreator): # settings for this creator columns_config = {} representations_config = {} + folder_creation_config = {} def get_instance_attr_defs(self): return [ @@ -390,8 +391,7 @@ def _resolve_repre_path( return filepath - @staticmethod - def _validate_parents(project_name: str, product_item: ProductItem) -> list: + def _validate_parents(self, project_name: str, product_item: ProductItem) -> list: """ Ensure parent exists for provided product_item.folder_path Args: @@ -428,15 +428,26 @@ def _validate_parents(project_name: str, product_item: ProductItem) -> list: parent_data = [] for path in parent_paths: folder_entity = folders_by_path.get(path) - if not folder_entity: - # TODO This should be some artist friendy error - # raising 'CreatorError' - raise ValueError(f"Unknown parent folder {path}") name = path.rsplit("/", 1)[-1] + + # Folder exists, retrieve data from existing. + if folder_entity: + folder_type = folder_entity["folderType"] + + # Define folder type from settings. + else: + for folder_setting in self.folder_creation_config["folder_type_regexes"]: + if re.match(folder_setting["regex"], name): + folder_type = folder_setting["folder_type"] + break + else: + folder_type = "Folder" # default + parent_data.append({ - "folder_type": folder_entity["folderType"], + "folder_type": folder_type, "entity_name": name }) + return parent_data @@ -526,6 +537,13 @@ def _get_data_from_csv( task_entities_by_folder_id[folder_id].append(task_entity) missing_tasks: Set[str] = set() + if missing_paths and not self.folder_creation_config["enabled"]: + error_msg = ( + "Folder creation is disabled but found missing folder(s): %r" % + ",".join(missing_paths) + ) + raise CreatorError(error_msg) + for product_item in product_items_by_name.values(): folder_path = product_item.folder_path @@ -908,14 +926,14 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): } ) # TODO create new task from provided task name - if product_item.task_name: - tasks = instance_data.setdefault("tasks", []) - tasks.append( - { - "name": product_item.task_name, - "type": "Generic" - } - ) + #if product_item.task_name: + # tasks = instance_data.setdefault("tasks", []) + # tasks.append( + # { + # "name": product_item.task_name, + # "type": "Generic" + # } + # ) # create new instance new_instance: CreatedInstance = CreatedInstance( diff --git a/server/settings/creator_plugins.py b/server/settings/creator_plugins.py index 9fca980..9a3047e 100644 --- a/server/settings/creator_plugins.py +++ b/server/settings/creator_plugins.py @@ -128,6 +128,30 @@ def validate_unique_outputs(cls, value): return value +class FolderTypeRegexItem(BaseSettingsModel): + _layout = "expanded" + regex: str = SettingsField("", title="Folder Regex") + folder_type: str = SettingsField("", title="Folder Type") + + +class FolderCreationConfigModel(BaseSettingsModel): + """Allow to create folder hierarchy when non-existing.""" + + enabled: bool = SettingsField( + title="Enabled folder creation", + default=False, + ) + + folder_type_regexes: list[FolderTypeRegexItem] = SettingsField( + default_factory=FolderTypeRegexItem, + description=( + "Using Regex expressions to create missing folders. \nThose can be used" + " to define which folder types are used for new folder creation" + " depending on their names." + ) + ) + + class IngestCSVPluginModel(BaseSettingsModel): """Allows to publish multiple video files in one go.
Name of matching asset is parsed from file names ('asset.mov', 'asset_v001.mov', @@ -148,6 +172,11 @@ class IngestCSVPluginModel(BaseSettingsModel): default_factory=RepresentationConfigModel ) + folder_creation_config: FolderCreationConfigModel = SettingsField( + title="Folder creation config", + default_factory=FolderCreationConfigModel + ) + class TrayPublisherCreatePluginsModel(BaseSettingsModel): BatchMovieCreator: BatchMovieCreatorPlugin = SettingsField( @@ -336,6 +365,13 @@ class TrayPublisherCreatePluginsModel(BaseSettingsModel): ] } ] - } + }, + "folder_creation_config": { + "enabled": False, + "folder_type_regexes": [ + {"regex": "(sh.*)", "folder_type": "Shot"}, + {"regex": "(seq.*)", "folder_type": "Sequence"} + ], + } } } From f199802fe994c90dc54f74f59cc4fc30852b2451 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 15 Nov 2024 15:28:54 +0100 Subject: [PATCH 4/8] Update folder type field in creator_plugins.py Added enum_resolver and description to folder_type field for better clarity and functionality. --- server/settings/creator_plugins.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/server/settings/creator_plugins.py b/server/settings/creator_plugins.py index 9a3047e..2ba7a23 100644 --- a/server/settings/creator_plugins.py +++ b/server/settings/creator_plugins.py @@ -1,5 +1,9 @@ from pydantic import validator -from ayon_server.settings import BaseSettingsModel, SettingsField +from ayon_server.settings import ( + BaseSettingsModel, + SettingsField, + folder_types_enum +) from ayon_server.settings.validators import ensure_unique_names from ayon_server.exceptions import BadRequestException @@ -131,7 +135,13 @@ def validate_unique_outputs(cls, value): class FolderTypeRegexItem(BaseSettingsModel): _layout = "expanded" regex: str = SettingsField("", title="Folder Regex") - folder_type: str = SettingsField("", title="Folder Type") + folder_type: str = SettingsField( + "Folder", + title="Folder Type", + enum_resolver=folder_types_enum, + description=( + "Project's Anatomy folder type to create when regex matches."), + ) class FolderCreationConfigModel(BaseSettingsModel): @@ -175,7 +185,7 @@ class IngestCSVPluginModel(BaseSettingsModel): folder_creation_config: FolderCreationConfigModel = SettingsField( title="Folder creation config", default_factory=FolderCreationConfigModel - ) + ) class TrayPublisherCreatePluginsModel(BaseSettingsModel): @@ -372,6 +382,6 @@ class TrayPublisherCreatePluginsModel(BaseSettingsModel): {"regex": "(sh.*)", "folder_type": "Shot"}, {"regex": "(seq.*)", "folder_type": "Sequence"} ], - } + } } } From 42044f4971d78341ed1e1c318674fb89bffcbfd4 Mon Sep 17 00:00:00 2001 From: "robin@ynput.io" Date: Mon, 18 Nov 2024 13:48:31 -0500 Subject: [PATCH 5/8] Add task settings and rework shot family. --- .../plugins/create/create_csv_ingest.py | 41 ++++++++++++++----- server/settings/creator_plugins.py | 34 ++++++++++++++- 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index 4c0e065..70d85e5 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -838,6 +838,24 @@ def _prepare_representations( explicit_output_name ) + def _get_task_type_from_task_name(self, task_name: str): + """ Retrieve task type from task name. + + Args: + task_name (str): The task name. + + Returns: + str. The task type computed from settings. + """ + for task_setting in self.folder_creation_config["task_type_regexes"]: + if re.match(task_setting["regex"], name): + folder_type = task_setting["task_type"] + break + else: + task_type = self.folder_creation_config["task_create_type"] + + return task_type + def _create_instances_from_csv_data(self, csv_dir: str, filename: str): """Create instances from csv data""" # from special function get all data from csv file and convert them @@ -917,23 +935,24 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): if product_item.has_promised_context: hierarchy, _ = folder_path.rsplit("/", 1) - families.append("csv_ingest_shot") + families.append("shot") instance_data.update( { "newHierarchyIntegration": True, "hierarchy": hierarchy, - "parents": product_item.parents + "parents": product_item.parents, + "families": families, + "heroTrack": True, } ) - # TODO create new task from provided task name - #if product_item.task_name: - # tasks = instance_data.setdefault("tasks", []) - # tasks.append( - # { - # "name": product_item.task_name, - # "type": "Generic" - # } - # ) + if product_item.task_name: + task_type = self._get_task_type_from_task_name( + product_item.task_name + ) + tasks = instance_data.setdefault("tasks", {}) + tasks[product_item.task_name] = { + "type": task_type + } # create new instance new_instance: CreatedInstance = CreatedInstance( diff --git a/server/settings/creator_plugins.py b/server/settings/creator_plugins.py index 2ba7a23..fb4a69f 100644 --- a/server/settings/creator_plugins.py +++ b/server/settings/creator_plugins.py @@ -2,7 +2,8 @@ from ayon_server.settings import ( BaseSettingsModel, SettingsField, - folder_types_enum + folder_types_enum, + task_types_enum, ) from ayon_server.settings.validators import ensure_unique_names from ayon_server.exceptions import BadRequestException @@ -144,6 +145,18 @@ class FolderTypeRegexItem(BaseSettingsModel): ) +class TaskTypeRegexItem(BaseSettingsModel): + _layout = "expanded" + regex: str = SettingsField("", title="Task Regex") + task_type: str = SettingsField( + "", + title="Task Type", + enum_resolver=task_types_enum, + description=( + "New task type to create when regex matches."), + ) + + class FolderCreationConfigModel(BaseSettingsModel): """Allow to create folder hierarchy when non-existing.""" @@ -161,6 +174,23 @@ class FolderCreationConfigModel(BaseSettingsModel): ) ) + task_type_regexes: list[TaskTypeRegexItem] = SettingsField( + default_factory=TaskTypeRegexItem, + description=( + "Using Regex expressions to create missing tasks. \nThose can be used" + " to define which task types are used for new folder+task creation" + " depending on their names." + ) + ) + + task_create_type: str = SettingsField( + "", + title="Default Task Type", + enum_resolver=task_types_enum, + description=( + "Default task type for new task(s) creation."), + ) + class IngestCSVPluginModel(BaseSettingsModel): """Allows to publish multiple video files in one go.
Name of matching @@ -382,6 +412,8 @@ class TrayPublisherCreatePluginsModel(BaseSettingsModel): {"regex": "(sh.*)", "folder_type": "Shot"}, {"regex": "(seq.*)", "folder_type": "Sequence"} ], + "task_type_regexes": [], + "task_create_type": "Generic", } } } From 33852e190c92221122368b41580a39235a8d7d9e Mon Sep 17 00:00:00 2001 From: "robin@ynput.io" Date: Mon, 18 Nov 2024 13:57:15 -0500 Subject: [PATCH 6/8] Add task settings and rework shot family. --- .../plugins/create/create_csv_ingest.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index 70d85e5..8edf218 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -429,6 +429,7 @@ def _validate_parents(self, project_name: str, product_item: ProductItem) -> lis for path in parent_paths: folder_entity = folders_by_path.get(path) name = path.rsplit("/", 1)[-1] + folder_type = None # Folder exists, retrieve data from existing. if folder_entity: @@ -440,13 +441,14 @@ def _validate_parents(self, project_name: str, product_item: ProductItem) -> lis if re.match(folder_setting["regex"], name): folder_type = folder_setting["folder_type"] break - else: - folder_type = "Folder" # default - parent_data.append({ - "folder_type": folder_type, - "entity_name": name - }) + item = { + "entity_name": name, + } + if folder_type: + item["folder_type"] = folder_type + + parent_data.append(item) return parent_data From d557ad7840152a94583a7b84f09482f3637e0ede Mon Sep 17 00:00:00 2001 From: "robin@ynput.io" Date: Mon, 18 Nov 2024 14:04:33 -0500 Subject: [PATCH 7/8] Fix linting and task type creation. --- client/ayon_traypublisher/plugins/create/create_csv_ingest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index 8edf218..a7b1b97 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -850,8 +850,8 @@ def _get_task_type_from_task_name(self, task_name: str): str. The task type computed from settings. """ for task_setting in self.folder_creation_config["task_type_regexes"]: - if re.match(task_setting["regex"], name): - folder_type = task_setting["task_type"] + if re.match(task_setting["regex"], task_name): + task_type = task_setting["task_type"] break else: task_type = self.folder_creation_config["task_create_type"] From 94f1134375c58b1f202cc50b3c20b8e113b0aa77 Mon Sep 17 00:00:00 2001 From: "robin@ynput.io" Date: Tue, 19 Nov 2024 09:30:22 -0500 Subject: [PATCH 8/8] Address PR feedback. --- .../plugins/create/create_csv_ingest.py | 51 +++++++++++-------- server/settings/creator_plugins.py | 9 ++++ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py index a7b1b97..a63155c 100644 --- a/client/ayon_traypublisher/plugins/create/create_csv_ingest.py +++ b/client/ayon_traypublisher/plugins/create/create_csv_ingest.py @@ -391,8 +391,25 @@ def _resolve_repre_path( return filepath - def _validate_parents(self, project_name: str, product_item: ProductItem) -> list: - """ Ensure parent exists for provided product_item.folder_path + def _get_folder_type_from_regex_settings(self, folder_name: str) -> str: + """ Get the folder type that matches the regex settings. + + Args: + folder_name (str): The folder name. + + Returns: + str. The folder type to use. + """ + for folder_setting in self.folder_creation_config["folder_type_regexes"]: + if re.match(folder_setting["regex"], folder_name): + folder_type = folder_setting["folder_type"] + return folder_type + + return self.folder_creation_config["folder_create_type"] + + def _compute_parents_data(self, project_name: str, product_item: ProductItem) -> list: + """ Compute parent data when new hierarchy has to be created during the + publishing process. Args: project_name (str): The project name. @@ -429,7 +446,6 @@ def _validate_parents(self, project_name: str, product_item: ProductItem) -> lis for path in parent_paths: folder_entity = folders_by_path.get(path) name = path.rsplit("/", 1)[-1] - folder_type = None # Folder exists, retrieve data from existing. if folder_entity: @@ -437,17 +453,12 @@ def _validate_parents(self, project_name: str, product_item: ProductItem) -> lis # Define folder type from settings. else: - for folder_setting in self.folder_creation_config["folder_type_regexes"]: - if re.match(folder_setting["regex"], name): - folder_type = folder_setting["folder_type"] - break + folder_type = self._get_folder_type_from_regex_settings(name) item = { "entity_name": name, + "folder_type": folder_type, } - if folder_type: - item["folder_type"] = folder_type - parent_data.append(item) return parent_data @@ -552,16 +563,10 @@ def _get_data_from_csv( if folder_path in missing_paths: product_item.has_promised_context = True product_item.task_type = None - try: - product_item.parents = self._validate_parents( - project_name, - product_item - ) - except ValueError: - raise CreatorError( - f"Parent context must exists for new shots: {folder_path}" - ) - + product_item.parents = self._compute_parents_data( + project_name, + product_item + ) continue task_name = product_item.task_name @@ -936,7 +941,7 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): } if product_item.has_promised_context: - hierarchy, _ = folder_path.rsplit("/", 1) + hierarchy, folder_name = folder_path.rsplit("/", 1) families.append("shot") instance_data.update( { @@ -947,6 +952,10 @@ def _create_instances_from_csv_data(self, csv_dir: str, filename: str): "heroTrack": True, } ) + + folder_type = self._get_folder_type_from_regex_settings(folder_name) + instance_data["folder_type"] = folder_type + if product_item.task_name: task_type = self._get_task_type_from_task_name( product_item.task_name diff --git a/server/settings/creator_plugins.py b/server/settings/creator_plugins.py index fb4a69f..e337fd9 100644 --- a/server/settings/creator_plugins.py +++ b/server/settings/creator_plugins.py @@ -174,6 +174,14 @@ class FolderCreationConfigModel(BaseSettingsModel): ) ) + folder_create_type: str = SettingsField( + "Folder", + title="Default Folder Type", + enum_resolver=folder_types_enum, + description=( + "Default folder type for new folder(s) creation."), + ) + task_type_regexes: list[TaskTypeRegexItem] = SettingsField( default_factory=TaskTypeRegexItem, description=( @@ -412,6 +420,7 @@ class TrayPublisherCreatePluginsModel(BaseSettingsModel): {"regex": "(sh.*)", "folder_type": "Shot"}, {"regex": "(seq.*)", "folder_type": "Sequence"} ], + "folder_create_type": "Folder", "task_type_regexes": [], "task_create_type": "Generic", }