Skip to content

Commit

Permalink
Merge pull request #834 from ynput/enhancement/AY-6198_OCIO-fallback-…
Browse files Browse the repository at this point in the history
…for-profiles-and-templated-values

Refactor OCIO config handling, introduce fallback mechanism
  • Loading branch information
iLLiCiTiT authored Oct 2, 2024
2 parents 5142a07 + 0b9cea9 commit ddd1883
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 33 deletions.
76 changes: 56 additions & 20 deletions client/ayon_core/pipeline/colorspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,34 @@ def get_ocio_config_views(config_path):
)


def _get_config_path_from_profile_data(
profile, profile_type, template_data
):
"""Get config path from profile data.
Args:
profile (dict[str, Any]): Profile data.
profile_type (str): Profile type.
template_data (dict[str, Any]): Template data.
Returns:
dict[str, str]: Config data with path and template.
"""
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
}


def _get_global_config_data(
project_name,
host_name,
Expand All @@ -717,7 +745,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
Expand Down Expand Up @@ -755,30 +783,36 @@ 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"

published_product_data = profile["published_product"]
product_name = published_product_data["product_name"]
fallback_data = published_product_data["fallback"]

if product_name == "":
log.error(
"Colorspace OCIO config path cannot be set. "
"Profile is set to published product but `Product name` is empty."
)
return None

folder_info = template_data.get("folder")
if not folder_info:
log.warning("Folder info is missing.")
return None

log.info("Using fallback data for ocio config path.")
# in case no product was found we need to use fallback
fallback_type = fallback_data["fallback_type"]
return _get_config_path_from_profile_data(
fallback_data, fallback_type, template_data
)

folder_path = folder_info["path"]

product_name = profile["product_name"]
if folder_id is None:
folder_entity = ayon_api.get_folder_by_path(
project_name, folder_path, fields={"id"}
Expand All @@ -797,12 +831,13 @@ def _get_global_config_data(
fields={"id", "name"}
)
}

if not product_entities_by_name:
log.debug(
f"No product entities were found for folder '{folder_path}' with"
f" product name filter '{product_name}'."
# 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
)
return None

# Try to use exact match first, otherwise use first available product
product_entity = product_entities_by_name.get(product_name)
Expand Down Expand Up @@ -837,6 +872,7 @@ def _get_global_config_data(

path = get_representation_path_with_anatomy(repre_entity, anatomy)
template = repre_entity["attrib"]["template"]

return {
"path": path,
"template": template,
Expand Down
33 changes: 29 additions & 4 deletions server/settings/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@
from .publish_plugins import DEFAULT_PUBLISH_VALUES


def _convert_imageio_configs_0_4_5(overrides):
"""Imageio config settings did change to profiles since 0.4.5."""
imageio_overrides = overrides.get("imageio") or {}

# make sure settings are already converted to profiles
ocio_config_profiles = imageio_overrides.get("ocio_config_profiles")
if not ocio_config_profiles:
return

for profile in ocio_config_profiles:
if profile.get("type") != "product_name":
continue

profile["type"] = "published_product"
profile["published_product"] = {
"product_name": profile.pop("product_name"),
"fallback": {
"type": "builtin_path",
"builtin_path": "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio",
},
}


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 {}
Expand Down Expand Up @@ -76,7 +99,8 @@ def _convert_oiio_transcode_0_4_5(publish_overrides):
if "ExtractOIIOTranscode" not in publish_overrides:
return

transcode_profiles = publish_overrides["ExtractOIIOTranscode"].get("profiles")
transcode_profiles = publish_overrides["ExtractOIIOTranscode"].get(
"profiles")
if not transcode_profiles:
return

Expand All @@ -85,7 +109,7 @@ def _convert_oiio_transcode_0_4_5(publish_overrides):
if outputs is None:
return

for output in outputs :
for output in outputs:
# Already new settings
if "display_view" in output:
break
Expand All @@ -102,7 +126,7 @@ def _convert_oiio_transcode_0_4_5(publish_overrides):
}


def _conver_publish_plugins(overrides):
def _convert_publish_plugins(overrides):
if "publish" not in overrides:
return
_convert_validate_version_0_3_3(overrides["publish"])
Expand All @@ -114,5 +138,6 @@ def convert_settings_overrides(
overrides: dict[str, Any],
) -> dict[str, Any]:
_convert_imageio_configs_0_3_1(overrides)
_conver_publish_plugins(overrides)
_convert_imageio_configs_0_4_5(overrides)
_convert_publish_plugins(overrides)
return overrides
75 changes: 66 additions & 9 deletions server/settings/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
]


Expand All @@ -76,6 +83,49 @@ def _ocio_built_in_paths():
]


class FallbackProductModel(BaseSettingsModel):
_layout = "expanded"
fallback_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(
Expand All @@ -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",
)


Expand Down Expand Up @@ -294,7 +344,14 @@ def validate_json(cls, value):
"type": "builtin_path",
"builtin_path": "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio",
"custom_path": "",
"product_name": "",
"published_product": {
"product_name": "",
"fallback": {
"fallback_type": "builtin_path",
"builtin_path": "ACES 1.2",
"custom_path": ""
}
}
}
],
"file_rules": {
Expand Down

0 comments on commit ddd1883

Please sign in to comment.