Refactor OCIO config handling, introduce fallback mechanism

- Added function to extract config path from profile data
- Updated global config retrieval to use new function
- Introduced fallback mechanism for missing product entities
This commit is contained in:
Jakub Jezek 2024-07-31 13:54:41 +02:00
parent 1d727e83bf
commit d7a2c57fd8
No known key found for this signature in database
GPG key ID: 06DBD609ADF27FD9
3 changed files with 156 additions and 24 deletions

View file

@ -699,6 +699,33 @@ def get_ocio_config_views(config_path):
)
def _get_config_path_from_profile_data(
data, data_type, template_data) -> dict:
"""Get config path from profile data.
Args:
data (dict[str, Any]): Profile data.
data_type (str): Profile type.
template_data (dict[str, Any]): Template data.
Returns:
dict[str, str]: Config data with path and template.
"""
template = data[data_type]
result = StringTemplate.format_strict_template(
template, template_data
)
normalized_path = str(result.normalized())
if not os.path.exists(normalized_path):
log.warning(f"Path was not found '{normalized_path}'.")
return None
return {
"path": normalized_path,
"template": template
}
def _get_global_config_data(
project_name,
host_name,
@ -717,7 +744,7 @@ def _get_global_config_data(
2. Custom path to ocio config.
3. Path to 'ocioconfig' representation on product. Name of product can be
defined in settings. Product name can be regex but exact match is
always preferred.
always preferred. Fallback can be defined in case no product is found.
None is returned when no profile is found, when path
@ -755,19 +782,8 @@ def _get_global_config_data(
profile_type = profile["type"]
if profile_type in ("builtin_path", "custom_path"):
template = profile[profile_type]
result = StringTemplate.format_strict_template(
template, template_data
)
normalized_path = str(result.normalized())
if not os.path.exists(normalized_path):
log.warning(f"Path was not found '{normalized_path}'.")
return None
return {
"path": normalized_path,
"template": template
}
return _get_config_path_from_profile_data(
profile, profile_type, template_data)
# TODO decide if this is the right name for representation
repre_name = "ocioconfig"
@ -778,7 +794,21 @@ def _get_global_config_data(
return None
folder_path = folder_info["path"]
product_name = profile["product_name"]
# Backward compatibility for old projects
# TODO remove in future 0.4.4 onwards
product_name = profile.get("product_name")
# TODO: this should be required after backward compatibility is removed
fallback_data = None
published_product_data = profile.get("published_product")
if product_name is None and published_product_data is None:
log.warning("Product name or published product is missing.")
return None
if published_product_data:
product_name = published_product_data["product_name"]
fallback_data = published_product_data["fallback"]
if folder_id is None:
folder_entity = ayon_api.get_folder_by_path(
project_name, folder_path, fields={"id"}
@ -798,6 +828,13 @@ def _get_global_config_data(
)
}
if not product_entities_by_name:
# TODO: make this required in future 0.4.4 onwards
if fallback_data:
# in case no product was found we need to use fallback
fallback_type = fallback_data["type"]
return _get_config_path_from_profile_data(
fallback_data, fallback_type, template_data
)
log.debug(
f"No product entities were found for folder '{folder_path}' with"
f" product name filter '{product_name}'."

View file

@ -4,6 +4,43 @@ from typing import Any
from .publish_plugins import DEFAULT_PUBLISH_VALUES
def _convert_imageio_configs_0_4_3(overrides):
"""Imageio config settings did change to profiles since 0.4.3."""
imageio_overrides = overrides.get("imageio") or {}
# make sure settings are already converted to profiles
if (
"ocio_config_profiles" not in imageio_overrides
):
return
ocio_config_profiles = imageio_overrides["ocio_config_profiles"]
for inx, profile in enumerate(ocio_config_profiles):
if profile["type"] != "product_name":
continue
# create new profile
new_profile = {
"type": "published_product",
"published_product": {
"product_name": profile["product_name"],
"fallback": {
"type": "builtin_path",
"builtin_path": "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio",
},
},
"host_names": profile["host_names"],
"task_names": profile["task_names"],
"task_types": profile["task_types"],
"custom_path": profile["custom_path"],
"builtin_path": profile["builtin_path"],
}
# replace old profile with new profile
ocio_config_profiles[inx] = new_profile
def _convert_imageio_configs_0_3_1(overrides):
"""Imageio config settings did change to profiles since 0.3.1. ."""
imageio_overrides = overrides.get("imageio") or {}
@ -82,5 +119,6 @@ def convert_settings_overrides(
overrides: dict[str, Any],
) -> dict[str, Any]:
_convert_imageio_configs_0_3_1(overrides)
_convert_imageio_configs_0_4_3(overrides)
_conver_publish_plugins(overrides)
return overrides

View file

@ -58,7 +58,14 @@ def _ocio_config_profile_types():
return [
{"value": "builtin_path", "label": "AYON built-in OCIO config"},
{"value": "custom_path", "label": "Path to OCIO config"},
{"value": "product_name", "label": "Published product"},
{"value": "published_product", "label": "Published product"},
]
def _fallback_ocio_config_profile_types():
return [
{"value": "builtin_path", "label": "AYON built-in OCIO config"},
{"value": "custom_path", "label": "Path to OCIO config"},
]
@ -76,6 +83,49 @@ def _ocio_built_in_paths():
]
class FallbackProductModel(BaseSettingsModel):
_layout = "expanded"
type: str = SettingsField(
title="Fallback config type",
enum_resolver=_fallback_ocio_config_profile_types,
conditionalEnum=True,
default="builtin_path",
description=(
"Type of config which needs to be used in case published "
"product is not found."
),
)
builtin_path: str = SettingsField(
"ACES 1.2",
title="Built-in OCIO config",
enum_resolver=_ocio_built_in_paths,
description=(
"AYON ocio addon distributed OCIO config. "
"Activated addon in bundle is required: 'ayon_ocio' >= 1.1.1"
),
)
custom_path: str = SettingsField(
"",
title="OCIO config path",
description="Path to OCIO config. Anatomy formatting is supported.",
)
class PublishedProductModel(BaseSettingsModel):
_layout = "expanded"
product_name: str = SettingsField(
"",
title="Product name",
description=(
"Context related published product name to get OCIO config from. "
"Partial match is supported via use of regex expression."
),
)
fallback: FallbackProductModel = SettingsField(
default_factory=FallbackProductModel,
)
class CoreImageIOConfigProfilesModel(BaseSettingsModel):
_layout = "expanded"
host_names: list[str] = SettingsField(
@ -102,19 +152,19 @@ class CoreImageIOConfigProfilesModel(BaseSettingsModel):
"ACES 1.2",
title="Built-in OCIO config",
enum_resolver=_ocio_built_in_paths,
description=(
"AYON ocio addon distributed OCIO config. "
"Activated addon in bundle is required: 'ayon_ocio' >= 1.1.1"
),
)
custom_path: str = SettingsField(
"",
title="OCIO config path",
description="Path to OCIO config. Anatomy formatting is supported.",
)
product_name: str = SettingsField(
"",
title="Product name",
description=(
"Published product name to get OCIO config from. "
"Partial match is supported."
),
published_product: PublishedProductModel = SettingsField(
default_factory=PublishedProductModel,
title="Published product",
)
@ -294,7 +344,14 @@ DEFAULT_VALUES = {
"type": "builtin_path",
"builtin_path": "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio",
"custom_path": "",
"product_name": "",
"published_product": {
"product_name": "",
"fallback": {
"type": "builtin_path",
"builtin_path": "ACES 1.2",
"custom_path": ""
}
}
}
],
"file_rules": {