mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
🐶 some type hints and linting changes
This commit is contained in:
parent
4b3220c1de
commit
f3beea1ff8
5 changed files with 354 additions and 354 deletions
|
|
@ -1,123 +1,107 @@
|
|||
"""Create module for Ayon Core."""
|
||||
from .constants import (
|
||||
PRODUCT_NAME_ALLOWED_SYMBOLS,
|
||||
DEFAULT_PRODUCT_TEMPLATE,
|
||||
PRE_CREATE_THUMBNAIL_KEY,
|
||||
DEFAULT_VARIANT_VALUE,
|
||||
PRE_CREATE_THUMBNAIL_KEY,
|
||||
PRODUCT_NAME_ALLOWED_SYMBOLS,
|
||||
)
|
||||
from .context import CreateContext
|
||||
from .creator_plugins import (
|
||||
AutoCreator,
|
||||
BaseCreator,
|
||||
Creator,
|
||||
HiddenCreator,
|
||||
cache_and_get_instances,
|
||||
deregister_creator_plugin,
|
||||
deregister_creator_plugin_path,
|
||||
discover_creator_plugins,
|
||||
discover_legacy_creator_plugins,
|
||||
get_legacy_creator_by_name,
|
||||
register_creator_plugin,
|
||||
register_creator_plugin_path,
|
||||
)
|
||||
from .exceptions import (
|
||||
UnavailableSharedData,
|
||||
ImmutableKeyError,
|
||||
HostMissRequiredMethod,
|
||||
ConvertorsOperationFailed,
|
||||
ConvertorsFindFailed,
|
||||
ConvertorsConversionFailed,
|
||||
ConvertorsFindFailed,
|
||||
ConvertorsOperationFailed,
|
||||
CreatorError,
|
||||
CreatorsCreateFailed,
|
||||
CreatorsCollectionFailed,
|
||||
CreatorsSaveFailed,
|
||||
CreatorsRemoveFailed,
|
||||
CreatorsCreateFailed,
|
||||
CreatorsOperationFailed,
|
||||
CreatorsRemoveFailed,
|
||||
CreatorsSaveFailed,
|
||||
HostMissRequiredMethod,
|
||||
ImmutableKeyError,
|
||||
TaskNotSetError,
|
||||
TemplateFillError,
|
||||
UnavailableSharedData,
|
||||
)
|
||||
from .legacy_create import (
|
||||
LegacyCreator,
|
||||
legacy_create,
|
||||
)
|
||||
from .product_name import (
|
||||
get_product_name,
|
||||
get_product_name_template,
|
||||
)
|
||||
from .structures import (
|
||||
CreatedInstance,
|
||||
ConvertorItem,
|
||||
AttributeValues,
|
||||
ConvertorItem,
|
||||
CreatedInstance,
|
||||
CreatorAttributeValues,
|
||||
PublishAttributeValues,
|
||||
PublishAttributes,
|
||||
PublishAttributeValues,
|
||||
)
|
||||
from .utils import (
|
||||
get_last_versions_for_instances,
|
||||
get_next_versions_for_instances,
|
||||
)
|
||||
|
||||
from .product_name import (
|
||||
get_product_name,
|
||||
get_product_name_template,
|
||||
)
|
||||
|
||||
from .creator_plugins import (
|
||||
BaseCreator,
|
||||
Creator,
|
||||
AutoCreator,
|
||||
HiddenCreator,
|
||||
|
||||
discover_legacy_creator_plugins,
|
||||
get_legacy_creator_by_name,
|
||||
|
||||
discover_creator_plugins,
|
||||
register_creator_plugin,
|
||||
deregister_creator_plugin,
|
||||
register_creator_plugin_path,
|
||||
deregister_creator_plugin_path,
|
||||
|
||||
cache_and_get_instances,
|
||||
)
|
||||
|
||||
from .context import CreateContext
|
||||
|
||||
from .legacy_create import (
|
||||
LegacyCreator,
|
||||
legacy_create,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"PRODUCT_NAME_ALLOWED_SYMBOLS",
|
||||
"DEFAULT_PRODUCT_TEMPLATE",
|
||||
"PRE_CREATE_THUMBNAIL_KEY",
|
||||
"DEFAULT_VARIANT_VALUE",
|
||||
"PRE_CREATE_THUMBNAIL_KEY",
|
||||
"PRODUCT_NAME_ALLOWED_SYMBOLS",
|
||||
|
||||
"UnavailableSharedData",
|
||||
"ImmutableKeyError",
|
||||
"HostMissRequiredMethod",
|
||||
"ConvertorsOperationFailed",
|
||||
"ConvertorsFindFailed",
|
||||
"ConvertorsConversionFailed",
|
||||
"CreatorError",
|
||||
"CreatorsCreateFailed",
|
||||
"CreatorsCollectionFailed",
|
||||
"CreatorsSaveFailed",
|
||||
"CreatorsRemoveFailed",
|
||||
"CreatorsOperationFailed",
|
||||
"TaskNotSetError",
|
||||
"TemplateFillError",
|
||||
|
||||
"CreatedInstance",
|
||||
"ConvertorItem",
|
||||
"AttributeValues",
|
||||
"AutoCreator",
|
||||
"BaseCreator",
|
||||
"ConvertorItem",
|
||||
"ConvertorsConversionFailed",
|
||||
"ConvertorsFindFailed",
|
||||
"ConvertorsOperationFailed",
|
||||
"CreateContext",
|
||||
"CreatedInstance",
|
||||
"Creator",
|
||||
"CreatorAttributeValues",
|
||||
"CreatorError",
|
||||
"CreatorError",
|
||||
"CreatorsCollectionFailed",
|
||||
"CreatorsCreateFailed",
|
||||
"CreatorsOperationFailed",
|
||||
"CreatorsRemoveFailed",
|
||||
"CreatorsSaveFailed",
|
||||
"HiddenCreator",
|
||||
"HostMissRequiredMethod",
|
||||
"ImmutableKeyError",
|
||||
"LegacyCreator",
|
||||
"PublishAttributeValues",
|
||||
"PublishAttributes",
|
||||
|
||||
"get_last_versions_for_instances",
|
||||
"get_next_versions_for_instances",
|
||||
|
||||
"get_product_name",
|
||||
"get_product_name_template",
|
||||
|
||||
"CreatorError",
|
||||
|
||||
"BaseCreator",
|
||||
"Creator",
|
||||
"AutoCreator",
|
||||
"HiddenCreator",
|
||||
|
||||
"discover_legacy_creator_plugins",
|
||||
"get_legacy_creator_by_name",
|
||||
|
||||
"discover_creator_plugins",
|
||||
"register_creator_plugin",
|
||||
"deregister_creator_plugin",
|
||||
"register_creator_plugin_path",
|
||||
"deregister_creator_plugin_path",
|
||||
"TaskNotSetError",
|
||||
"TemplateFillError",
|
||||
"UnavailableSharedData",
|
||||
|
||||
"cache_and_get_instances",
|
||||
|
||||
"CreateContext",
|
||||
|
||||
"LegacyCreator",
|
||||
"deregister_creator_plugin",
|
||||
"deregister_creator_plugin_path",
|
||||
"discover_creator_plugins",
|
||||
"discover_legacy_creator_plugins",
|
||||
"get_last_versions_for_instances",
|
||||
"get_legacy_creator_by_name",
|
||||
"get_next_versions_for_instances",
|
||||
"get_product_name",
|
||||
"get_product_name_template",
|
||||
"legacy_create",
|
||||
"register_creator_plugin",
|
||||
"register_creator_plugin_path",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,16 @@
|
|||
"""Implementation of TrackChangesItem class."""
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
from typing import TYPE_CHECKING, Any, Optional, TypeVar
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Self
|
||||
|
||||
_EMPTY_VALUE = object()
|
||||
|
||||
T = TypeVar("T", bound="TrackChangesItem")
|
||||
|
||||
|
||||
class TrackChangesItem:
|
||||
"""Helper object to track changes in data.
|
||||
|
|
@ -39,26 +48,26 @@ class TrackChangesItem:
|
|||
... "key_3": "value_3"
|
||||
... }
|
||||
|
||||
>>> changes = TrackChangesItem(old_value, new_value)
|
||||
>>> changes.changed
|
||||
>>> tracked_changes = TrackChangesItem(old_value, new_value)
|
||||
>>> tracked_changes.changed
|
||||
True
|
||||
|
||||
>>> changes["key_2"]["key_sub_1"].new_value is None
|
||||
>>> tracked_changes["key_2"]["key_sub_1"].new_value is None
|
||||
True
|
||||
|
||||
>>> list(sorted(changes.changed_keys))
|
||||
>>> list(sorted(tracked_changes.changed_keys))
|
||||
['key_2', 'key_3']
|
||||
|
||||
>>> changes["key_2"]["key_sub_2"]["enabled"].changed
|
||||
>>> tracked_changes["key_2"]["key_sub_2"]["enabled"].changed
|
||||
True
|
||||
|
||||
>>> changes["key_2"].removed_keys
|
||||
>>> tracked_changes["key_2"].removed_keys
|
||||
{'key_sub_1'}
|
||||
|
||||
>>> list(sorted(changes["key_2"].available_keys))
|
||||
>>> list(sorted(tracked_changes["key_2"].available_keys))
|
||||
['key_sub_1', 'key_sub_2', 'key_sub_3']
|
||||
|
||||
>>> changes.new_value == new_value
|
||||
>>> tracked_changes.new_value == new_value
|
||||
True
|
||||
|
||||
# Get only changed values
|
||||
|
|
@ -73,7 +82,8 @@ class TrackChangesItem:
|
|||
new_value (Any): New value.
|
||||
"""
|
||||
|
||||
def __init__(self, old_value, new_value):
|
||||
def __init__(self, old_value: Any, new_value: Any): # noqa: ANN401
|
||||
"""Constructor of TrackChangesItem."""
|
||||
self._changed = old_value != new_value
|
||||
# Resolve if value is '_EMPTY_VALUE' after comparison of the values
|
||||
if old_value is _EMPTY_VALUE:
|
||||
|
|
@ -86,76 +96,94 @@ class TrackChangesItem:
|
|||
self._old_is_dict = isinstance(old_value, dict)
|
||||
self._new_is_dict = isinstance(new_value, dict)
|
||||
|
||||
self._old_keys = None
|
||||
self._new_keys = None
|
||||
self._available_keys = None
|
||||
self._removed_keys = None
|
||||
self._old_keys: set[str] = set()
|
||||
self._new_keys: set[str] = set()
|
||||
self._available_keys: set[str] = set()
|
||||
self._removed_keys: set[str] = set()
|
||||
|
||||
self._changed_keys = None
|
||||
self._changed_keys: set[str] = set()
|
||||
|
||||
self._sub_items = None
|
||||
self._sub_items: dict[str, Self] = {}
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Getter looks into subitems if object is dictionary."""
|
||||
def __getitem__(self, key: str) -> Self:
|
||||
"""Getter looks into subitems if object is dictionary.
|
||||
|
||||
if self._sub_items is None:
|
||||
Args:
|
||||
key (str): Key to get sub item.
|
||||
|
||||
Returns:
|
||||
TrackChangesItem: Sub item of the object.
|
||||
|
||||
"""
|
||||
if not self._sub_items:
|
||||
self._prepare_sub_items()
|
||||
return self._sub_items[key]
|
||||
# ignore mypy error as Self won't work in Python 3.9 yet
|
||||
return self._sub_items[key] # type: ignore[return-value]
|
||||
|
||||
def __bool__(self):
|
||||
"""Boolean of object is if old and new value are the same."""
|
||||
"""Boolean of object is if old and new value are the same.
|
||||
|
||||
Returns:
|
||||
bool: If object is changed.
|
||||
|
||||
"""
|
||||
return self._changed
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""Try to get sub item."""
|
||||
def get(self,
|
||||
key: str, default: Optional[Self] = None) -> Self:
|
||||
"""Try to get sub item.
|
||||
|
||||
if self._sub_items is None:
|
||||
Args:
|
||||
key (str): Key to get sub item.
|
||||
default (Optional[str]): Default value if key is not found.
|
||||
|
||||
Returns:
|
||||
TrackChangesItem: Sub item of the object.
|
||||
|
||||
"""
|
||||
if not self._sub_items:
|
||||
self._prepare_sub_items()
|
||||
return self._sub_items.get(key, default)
|
||||
return self._sub_items.get(
|
||||
key, default) # type: ignore[return-value, arg-type]
|
||||
|
||||
@property
|
||||
def old_value(self):
|
||||
def old_value(self) -> Any: # noqa: ANN401
|
||||
"""Get copy of old value.
|
||||
|
||||
Returns:
|
||||
Any: Whatever old value was.
|
||||
"""
|
||||
|
||||
return copy.deepcopy(self._old_value)
|
||||
|
||||
@property
|
||||
def new_value(self):
|
||||
def new_value(self) -> Any: # noqa: ANN401
|
||||
"""Get copy of new value.
|
||||
|
||||
Returns:
|
||||
Any: Whatever new value was.
|
||||
"""
|
||||
|
||||
return copy.deepcopy(self._new_value)
|
||||
|
||||
@property
|
||||
def changed(self):
|
||||
def changed(self) -> bool:
|
||||
"""Value changed.
|
||||
|
||||
Returns:
|
||||
bool: If data changed.
|
||||
"""
|
||||
|
||||
return self._changed
|
||||
|
||||
@property
|
||||
def is_dict(self):
|
||||
def is_dict(self) -> bool:
|
||||
"""Object can be used as dictionary.
|
||||
|
||||
Returns:
|
||||
bool: When can be used that way.
|
||||
"""
|
||||
|
||||
return self._old_is_dict or self._new_is_dict
|
||||
|
||||
@property
|
||||
def changes(self):
|
||||
def changes(self) -> dict[str, tuple]:
|
||||
"""Get changes in raw data.
|
||||
|
||||
This method should be used only if 'is_dict' value is 'True'.
|
||||
|
|
@ -165,68 +193,67 @@ class TrackChangesItem:
|
|||
(<old value>, <new value>). If 'is_dict' is 'False' then
|
||||
output is always empty dictionary.
|
||||
"""
|
||||
|
||||
output = {}
|
||||
output: dict[str, tuple] = {}
|
||||
if not self.is_dict:
|
||||
return output
|
||||
|
||||
old_value = self.old_value
|
||||
new_value = self.new_value
|
||||
for key in self.changed_keys:
|
||||
_old = None
|
||||
_new = None
|
||||
old = None
|
||||
new = None
|
||||
if self._old_is_dict:
|
||||
_old = old_value.get(key)
|
||||
old = old_value.get(key)
|
||||
if self._new_is_dict:
|
||||
_new = new_value.get(key)
|
||||
output[key] = (_old, _new)
|
||||
new = new_value.get(key)
|
||||
output[key] = (old, new)
|
||||
return output
|
||||
|
||||
# Methods/properties that can be used when 'is_dict' is 'True'
|
||||
@property
|
||||
def old_keys(self):
|
||||
def old_keys(self) -> set[str]:
|
||||
"""Keys from old value.
|
||||
|
||||
Empty set is returned if old value is not a dict.
|
||||
|
||||
Returns:
|
||||
Set[str]: Keys from old value.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self._old_keys is None:
|
||||
self._prepare_keys()
|
||||
return set(self._old_keys)
|
||||
|
||||
@property
|
||||
def new_keys(self):
|
||||
def new_keys(self) -> set[str]:
|
||||
"""Keys from new value.
|
||||
|
||||
Empty set is returned if old value is not a dict.
|
||||
|
||||
Returns:
|
||||
Set[str]: Keys from new value.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self._new_keys is None:
|
||||
self._prepare_keys()
|
||||
return set(self._new_keys)
|
||||
|
||||
@property
|
||||
def changed_keys(self):
|
||||
def changed_keys(self) -> set[str]:
|
||||
"""Keys that has changed from old to new value.
|
||||
|
||||
Empty set is returned if both old and new value are not a dict.
|
||||
|
||||
Returns:
|
||||
Set[str]: Keys of changed keys.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self._changed_keys is None:
|
||||
self._prepare_sub_items()
|
||||
return set(self._changed_keys)
|
||||
|
||||
@property
|
||||
def available_keys(self):
|
||||
def available_keys(self) -> set[str]:
|
||||
"""All keys that are available in old and new value.
|
||||
|
||||
Empty set is returned if both old and new value are not a dict.
|
||||
|
|
@ -234,25 +261,25 @@ class TrackChangesItem:
|
|||
|
||||
Returns:
|
||||
Set[str]: All keys from old and new value.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self._available_keys is None:
|
||||
self._prepare_keys()
|
||||
return set(self._available_keys)
|
||||
|
||||
@property
|
||||
def removed_keys(self):
|
||||
def removed_keys(self) -> set[str]:
|
||||
"""Key that are not available in new value but were in old value.
|
||||
|
||||
Returns:
|
||||
Set[str]: All removed keys.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self._removed_keys is None:
|
||||
self._prepare_sub_items()
|
||||
return set(self._removed_keys)
|
||||
|
||||
def _prepare_keys(self):
|
||||
def _prepare_keys(self) -> None:
|
||||
old_keys = set()
|
||||
new_keys = set()
|
||||
if self._old_is_dict and self._new_is_dict:
|
||||
|
|
@ -270,7 +297,8 @@ class TrackChangesItem:
|
|||
self._available_keys = old_keys | new_keys
|
||||
self._removed_keys = old_keys - new_keys
|
||||
|
||||
def _prepare_sub_items(self):
|
||||
def _prepare_sub_items(self) -> None:
|
||||
"""Prepare sub items and changed keys."""
|
||||
sub_items = {}
|
||||
changed_keys = set()
|
||||
|
||||
|
|
@ -309,5 +337,6 @@ class TrackChangesItem:
|
|||
_EMPTY_VALUE, new_value.get(key)
|
||||
)
|
||||
|
||||
self._sub_items = sub_items
|
||||
# this is also not resolved correctly in Python 3.9 with Self type
|
||||
self._sub_items = sub_items # type: ignore[assignment]
|
||||
self._changed_keys = changed_keys
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
"""Constants for the create module."""
|
||||
|
||||
PRODUCT_NAME_ALLOWED_SYMBOLS = "a-zA-Z0-9_."
|
||||
DEFAULT_PRODUCT_TEMPLATE = "{family}{Variant}"
|
||||
PRE_CREATE_THUMBNAIL_KEY = "thumbnail_source"
|
||||
|
|
@ -5,8 +7,8 @@ DEFAULT_VARIANT_VALUE = "Main"
|
|||
|
||||
|
||||
__all__ = (
|
||||
"PRODUCT_NAME_ALLOWED_SYMBOLS",
|
||||
"DEFAULT_PRODUCT_TEMPLATE",
|
||||
"PRE_CREATE_THUMBNAIL_KEY",
|
||||
"DEFAULT_VARIANT_VALUE",
|
||||
"PRE_CREATE_THUMBNAIL_KEY",
|
||||
"PRODUCT_NAME_ALLOWED_SYMBOLS",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,74 +1,114 @@
|
|||
"""Context of instance creation."""
|
||||
from __future__ import annotations
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import dataclasses
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
import logging
|
||||
import traceback
|
||||
import collections
|
||||
import inspect
|
||||
from contextlib import contextmanager
|
||||
import typing
|
||||
from contextlib import contextmanager
|
||||
from typing import (
|
||||
Optional,
|
||||
Iterable,
|
||||
Tuple,
|
||||
List,
|
||||
Set,
|
||||
Dict,
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
List,
|
||||
NamedTuple,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
import pyblish.logic
|
||||
import pyblish.api
|
||||
import ayon_api
|
||||
import pyblish.api
|
||||
import pyblish.logic
|
||||
|
||||
from ayon_core.settings import get_project_settings
|
||||
from ayon_core.lib import is_func_signature_supported
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.lib.attribute_definitions import get_default_values
|
||||
from ayon_core.host import IPublishHost, IWorkfileHost
|
||||
from ayon_core.lib import is_func_signature_supported
|
||||
from ayon_core.lib.attribute_definitions import get_default_values
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.pipeline import Anatomy
|
||||
from ayon_core.pipeline.template_data import get_template_data
|
||||
from ayon_core.pipeline.plugin_discover import DiscoverResult
|
||||
from ayon_core.pipeline.template_data import get_template_data
|
||||
from ayon_core.settings import get_project_settings
|
||||
|
||||
from .exceptions import (
|
||||
CreatorError,
|
||||
CreatorsCreateFailed,
|
||||
CreatorsCollectionFailed,
|
||||
CreatorsSaveFailed,
|
||||
CreatorsRemoveFailed,
|
||||
ConvertorsFindFailed,
|
||||
ConvertorsConversionFailed,
|
||||
UnavailableSharedData,
|
||||
HostMissRequiredMethod,
|
||||
)
|
||||
from .changes import TrackChangesItem
|
||||
from .structures import PublishAttributes, ConvertorItem, InstanceContextInfo
|
||||
from .creator_plugins import (
|
||||
Creator,
|
||||
AutoCreator,
|
||||
discover_creator_plugins,
|
||||
Creator,
|
||||
discover_convertor_plugins,
|
||||
discover_creator_plugins,
|
||||
)
|
||||
if typing.TYPE_CHECKING:
|
||||
from .structures import CreatedInstance
|
||||
|
||||
# Import of functions and classes that were moved to different file
|
||||
# TODO Should be removed in future release - Added 24/08/28, 0.4.3-dev.1
|
||||
from .exceptions import (
|
||||
ImmutableKeyError, # noqa: F401
|
||||
CreatorsOperationFailed, # noqa: F401
|
||||
ConvertorsOperationFailed, # noqa: F401
|
||||
)
|
||||
from .structures import (
|
||||
AttributeValues, # noqa: F401
|
||||
CreatorAttributeValues, # noqa: F401
|
||||
PublishAttributeValues, # noqa: F401
|
||||
ConvertorsConversionFailed,
|
||||
ConvertorsFindFailed,
|
||||
CreatorError,
|
||||
CreatorsCollectionFailed,
|
||||
CreatorsCreateFailed,
|
||||
CreatorsRemoveFailed,
|
||||
CreatorsSaveFailed,
|
||||
HostMissRequiredMethod,
|
||||
UnavailableSharedData,
|
||||
)
|
||||
from .structures import ConvertorItem, InstanceContextInfo, PublishAttributes
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from ayon_core.host import HostBase
|
||||
from ayon_core.pipeline.create.structures import CreatedInstance
|
||||
|
||||
|
||||
# Changes of instances and context are send as tuple of 2 information
|
||||
UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"])
|
||||
class UpdateData(NamedTuple):
|
||||
""""Update data for instance.
|
||||
|
||||
Args:
|
||||
instance (CreatedInstance): Instance which was changed.
|
||||
changes (dict[str, Any]): Changes of instance.
|
||||
"""
|
||||
|
||||
# Instance which was changed
|
||||
instance: Optional[CreatedInstance]
|
||||
# Changes of instance.
|
||||
changes: dict[str, Any]
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ConvertorOperationInfo:
|
||||
"""Convertor operation information.
|
||||
|
||||
Args:
|
||||
identifier (str): Identifier of convertor.
|
||||
message (str): Message of convertor.
|
||||
traceback (str): Traceback of convertor.
|
||||
"""
|
||||
|
||||
identifier: str
|
||||
message: str
|
||||
traceback: str
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class CreatorOperationInfo:
|
||||
"""Creator operation information.
|
||||
|
||||
Args:
|
||||
creator_identifier (str): Identifier of creator.
|
||||
creator_label (str): Label of creator.
|
||||
message (str): Message of convertor.
|
||||
traceback (str): Traceback of convertor.
|
||||
"""
|
||||
|
||||
creator_identifier: str
|
||||
creator_label: str
|
||||
message: str
|
||||
traceback: str
|
||||
|
||||
|
||||
_NOT_SET = object()
|
||||
|
||||
INSTANCE_ADDED_TOPIC = "instances.added"
|
||||
|
|
@ -79,22 +119,45 @@ CREATE_ATTR_DEFS_CHANGED_TOPIC = "create.attr.defs.changed"
|
|||
PUBLISH_ATTR_DEFS_CHANGED_TOPIC = "publish.attr.defs.changed"
|
||||
|
||||
|
||||
def prepare_failed_convertor_operation_info(identifier, exc_info):
|
||||
def prepare_failed_convertor_operation_info(
|
||||
identifier: str, exc_info: tuple) -> ConvertorOperationInfo:
|
||||
"""Prepare convertor operation information.
|
||||
|
||||
Returns:
|
||||
ConvertorOperationInfo: Information about convertor operation.
|
||||
|
||||
"""
|
||||
exc_type, exc_value, exc_traceback = exc_info
|
||||
formatted_traceback = "".join(traceback.format_exception(
|
||||
exc_type, exc_value, exc_traceback
|
||||
))
|
||||
|
||||
return {
|
||||
"convertor_identifier": identifier,
|
||||
"message": str(exc_value),
|
||||
"traceback": formatted_traceback
|
||||
}
|
||||
return ConvertorOperationInfo(
|
||||
identifier=identifier,
|
||||
message=str(exc_value),
|
||||
traceback=formatted_traceback
|
||||
)
|
||||
|
||||
|
||||
def prepare_failed_creator_operation_info(
|
||||
identifier, label, exc_info, add_traceback=True
|
||||
):
|
||||
identifier: str,
|
||||
label: str,
|
||||
exc_info: tuple,
|
||||
*,
|
||||
add_traceback: bool = True
|
||||
) -> CreatorOperationInfo:
|
||||
"""Prepare creator operation information.
|
||||
|
||||
Args:
|
||||
identifier (str): Identifier of creator.
|
||||
label (str): Label of creator.
|
||||
exc_info (tuple): Exception information.
|
||||
add_traceback (bool): Add traceback to the message.
|
||||
|
||||
Returns:
|
||||
CreatorOperationInfo: Information about creator operation.
|
||||
|
||||
"""
|
||||
formatted_traceback = None
|
||||
exc_type, exc_value, exc_traceback = exc_info
|
||||
if add_traceback:
|
||||
|
|
@ -102,15 +165,16 @@ def prepare_failed_creator_operation_info(
|
|||
exc_type, exc_value, exc_traceback
|
||||
))
|
||||
|
||||
return {
|
||||
"creator_identifier": identifier,
|
||||
"creator_label": label,
|
||||
"message": str(exc_value),
|
||||
"traceback": formatted_traceback
|
||||
}
|
||||
return CreatorOperationInfo(
|
||||
creator_identifier=identifier,
|
||||
creator_label=label,
|
||||
message=str(exc_value),
|
||||
traceback=formatted_traceback
|
||||
)
|
||||
|
||||
|
||||
class BulkInfo:
|
||||
"""Bulk information."""
|
||||
def __init__(self):
|
||||
self._count = 0
|
||||
self._data = []
|
||||
|
|
@ -146,18 +210,19 @@ class BulkInfo:
|
|||
return data
|
||||
|
||||
|
||||
class CreateContext:
|
||||
class CreateContext: # noqa: PLR0904
|
||||
"""Context of instance creation.
|
||||
|
||||
Context itself also can store data related to whole creation (workfile).
|
||||
- those are mainly for Context publish plugins
|
||||
|
||||
Todos:
|
||||
Don't use 'AvalonMongoDB'. It's used only to keep track about current
|
||||
context which should be handled by host.
|
||||
Todo:
|
||||
This is now using PLR0904 to handle "too many public method" issue.
|
||||
It has around 70 of them and that is too much for one class. We
|
||||
should split this class into multiple classes.
|
||||
|
||||
Args:
|
||||
host(ModuleType): Host implementation which handles implementation and
|
||||
host(HostBase): Host implementation which handles implementation and
|
||||
global metadata.
|
||||
headless(bool): Context is created out of UI (Current not used).
|
||||
reset(bool): Reset context on initialization.
|
||||
|
|
@ -166,8 +231,14 @@ class CreateContext:
|
|||
"""
|
||||
|
||||
def __init__(
|
||||
self, host, headless=False, reset=True, discover_publish_plugins=True
|
||||
self,
|
||||
host: HostBase,
|
||||
*,
|
||||
headless: bool = False,
|
||||
reset: bool = True,
|
||||
discover_publish_plugins: bool = True,
|
||||
):
|
||||
"""Initialization of CreateContext."""
|
||||
self.host = host
|
||||
|
||||
# Prepare attribute for logger (Created on demand in `log` property)
|
||||
|
|
@ -185,12 +256,11 @@ class CreateContext:
|
|||
if missing_methods:
|
||||
host_is_valid = False
|
||||
joined_methods = ", ".join(
|
||||
['"{}"'.format(name) for name in missing_methods]
|
||||
[f'"{name}"' for name in missing_methods]
|
||||
)
|
||||
self.log.warning((
|
||||
self.log.warning(
|
||||
"Host miss required methods to be able use creation."
|
||||
" Missing methods: {}"
|
||||
).format(joined_methods))
|
||||
" Missing methods: %s", joined_methods)
|
||||
|
||||
self._current_project_name = None
|
||||
self._current_folder_path = None
|
||||
|
|
@ -281,7 +351,7 @@ class CreateContext:
|
|||
|
||||
def get_instance_by_id(
|
||||
self, instance_id: str
|
||||
) -> Optional["CreatedInstance"]:
|
||||
) -> Optional[CreatedInstance]:
|
||||
"""Receive instance by id.
|
||||
|
||||
Args:
|
||||
|
|
@ -326,7 +396,6 @@ class CreateContext:
|
|||
Returns:
|
||||
List[BaseCreator]: Sorted creator plugins by 'order' value.
|
||||
"""
|
||||
|
||||
return self.get_sorted_creators()
|
||||
|
||||
@property
|
||||
|
|
@ -336,23 +405,18 @@ class CreateContext:
|
|||
Returns:
|
||||
List[AutoCreator]: Sorted plugins by 'order' value.
|
||||
"""
|
||||
|
||||
return sorted(
|
||||
self.autocreators.values(), key=lambda creator: creator.order
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_host_misssing_methods(cls, host):
|
||||
def get_host_misssing_methods(cls, host: HostBase) -> Set[str]:
|
||||
"""Collect missing methods from host.
|
||||
|
||||
Args:
|
||||
host(ModuleType): Host implementaion.
|
||||
"""
|
||||
|
||||
missing = set(
|
||||
IPublishHost.get_missing_publish_methods(host)
|
||||
)
|
||||
return missing
|
||||
return set(IPublishHost.get_missing_publish_methods(host))
|
||||
|
||||
@property
|
||||
def host_is_valid(self):
|
||||
|
|
@ -371,7 +435,6 @@ class CreateContext:
|
|||
Returns:
|
||||
Union[str, None]: Project name.
|
||||
"""
|
||||
|
||||
return self._current_project_name
|
||||
|
||||
def get_current_folder_path(self) -> Optional[str]:
|
||||
|
|
@ -380,7 +443,6 @@ class CreateContext:
|
|||
Returns:
|
||||
Union[str, None]: Folder path.
|
||||
"""
|
||||
|
||||
return self._current_folder_path
|
||||
|
||||
def get_current_task_name(self) -> Optional[str]:
|
||||
|
|
@ -389,7 +451,6 @@ class CreateContext:
|
|||
Returns:
|
||||
Union[str, None]: Task name.
|
||||
"""
|
||||
|
||||
return self._current_task_name
|
||||
|
||||
def get_current_task_type(self) -> Optional[str]:
|
||||
|
|
@ -460,7 +521,6 @@ class CreateContext:
|
|||
Returns:
|
||||
Union[str, None]: Workfile path.
|
||||
"""
|
||||
|
||||
return self._current_workfile_path
|
||||
|
||||
def get_current_project_anatomy(self):
|
||||
|
|
@ -469,7 +529,6 @@ class CreateContext:
|
|||
Returns:
|
||||
Anatomy: Anatomy object ready to be used.
|
||||
"""
|
||||
|
||||
if self._current_project_anatomy is None:
|
||||
self._current_project_anatomy = Anatomy(
|
||||
self._current_project_name)
|
||||
|
|
@ -521,7 +580,6 @@ class CreateContext:
|
|||
Returns:
|
||||
bool: Context changed.
|
||||
"""
|
||||
|
||||
project_name, folder_path, task_name, workfile_path = (
|
||||
self._get_current_host_context()
|
||||
)
|
||||
|
|
@ -547,7 +605,6 @@ class CreateContext:
|
|||
|
||||
All changes will be lost if were not saved explicitely.
|
||||
"""
|
||||
|
||||
self.reset_preparation()
|
||||
|
||||
self.reset_current_context()
|
||||
|
|
@ -567,7 +624,6 @@ class CreateContext:
|
|||
Remove all thumbnail filepaths that are empty or lead to files which
|
||||
does not exist or of instances that are not available anymore.
|
||||
"""
|
||||
|
||||
invalid = set()
|
||||
for instance_id, path in self.thumbnail_paths_by_instance_id.items():
|
||||
instance_available = True
|
||||
|
|
@ -586,7 +642,6 @@ class CreateContext:
|
|||
|
||||
def reset_preparation(self):
|
||||
"""Prepare attributes that must be prepared/cleaned before reset."""
|
||||
|
||||
# Give ability to store shared data for collection phase
|
||||
self._collection_shared_data = {}
|
||||
|
||||
|
|
@ -600,7 +655,6 @@ class CreateContext:
|
|||
|
||||
def reset_finalization(self):
|
||||
"""Cleanup of attributes after reset."""
|
||||
|
||||
# Stop access to collection shared data
|
||||
self._collection_shared_data = None
|
||||
self.refresh_thumbnails()
|
||||
|
|
@ -635,7 +689,6 @@ class CreateContext:
|
|||
as current context information as that's where the metadata
|
||||
are stored. We should store the workfile (if is available) too.
|
||||
"""
|
||||
|
||||
project_name, folder_path, task_name, workfile_path = (
|
||||
self._get_current_host_context()
|
||||
)
|
||||
|
|
@ -659,16 +712,13 @@ class CreateContext:
|
|||
Reloads creators from preregistered paths and can load publish plugins
|
||||
if it's enabled on context.
|
||||
"""
|
||||
|
||||
self._reset_publish_plugins(discover_publish_plugins)
|
||||
self._reset_creator_plugins()
|
||||
self._reset_convertor_plugins()
|
||||
|
||||
def _reset_publish_plugins(self, discover_publish_plugins):
|
||||
from ayon_core.pipeline import AYONPyblishPluginMixin
|
||||
from ayon_core.pipeline.publish import (
|
||||
publish_plugins_discover
|
||||
)
|
||||
from ayon_core.pipeline.publish import publish_plugins_discover
|
||||
|
||||
discover_result = DiscoverResult(pyblish.api.Plugin)
|
||||
plugins_with_defs = []
|
||||
|
|
@ -732,7 +782,7 @@ class CreateContext:
|
|||
for creator_class in report.plugins:
|
||||
if inspect.isabstract(creator_class):
|
||||
self.log.debug(
|
||||
"Skipping abstract Creator {}".format(str(creator_class))
|
||||
f"Skipping abstract Creator {creator_class!s}"
|
||||
)
|
||||
continue
|
||||
|
||||
|
|
@ -749,10 +799,10 @@ class CreateContext:
|
|||
creator_class.host_name
|
||||
and creator_class.host_name != self.host_name
|
||||
):
|
||||
self.log.info((
|
||||
"Creator's host name \"{}\""
|
||||
" is not supported for current host \"{}\""
|
||||
).format(creator_class.host_name, self.host_name))
|
||||
self.log.info(
|
||||
f"Creator's host name \"{creator_class.host_name}\""
|
||||
f' is not supported for current host "{self.host_name}"'
|
||||
)
|
||||
continue
|
||||
|
||||
# TODO report initialization error
|
||||
|
|
@ -791,16 +841,16 @@ class CreateContext:
|
|||
for convertor_class in report.plugins:
|
||||
if inspect.isabstract(convertor_class):
|
||||
self.log.info(
|
||||
"Skipping abstract Creator {}".format(str(convertor_class))
|
||||
f"Skipping abstract Creator {convertor_class!s}"
|
||||
)
|
||||
continue
|
||||
|
||||
convertor_identifier = convertor_class.identifier
|
||||
if convertor_identifier in convertors_plugins:
|
||||
self.log.warning((
|
||||
self.log.warning(
|
||||
"Duplicated Converter identifier. "
|
||||
"Using first and skipping following"
|
||||
))
|
||||
)
|
||||
continue
|
||||
|
||||
convertors_plugins[convertor_identifier] = convertor_class(self)
|
||||
|
|
@ -1033,7 +1083,6 @@ class CreateContext:
|
|||
|
||||
def context_data_changes(self):
|
||||
"""Changes of attributes."""
|
||||
|
||||
return TrackChangesItem(
|
||||
self._original_context_data, self.context_data_to_store()
|
||||
)
|
||||
|
|
@ -1053,7 +1102,7 @@ class CreateContext:
|
|||
None, plugin_name
|
||||
)
|
||||
|
||||
def creator_adds_instance(self, instance: "CreatedInstance"):
|
||||
def creator_adds_instance(self, instance: CreatedInstance):
|
||||
"""Creator adds new instance to context.
|
||||
|
||||
Instances should be added only from creators.
|
||||
|
|
@ -1066,9 +1115,9 @@ class CreateContext:
|
|||
"""
|
||||
# Add instance to instances list
|
||||
if instance.id in self._instances_by_id:
|
||||
self.log.warning((
|
||||
"Instance with id {} is already added to context."
|
||||
).format(instance.id))
|
||||
self.log.warning(
|
||||
f"Instance with id {instance.id} is already added to context."
|
||||
)
|
||||
return
|
||||
|
||||
self._instances_by_id[instance.id] = instance
|
||||
|
|
@ -1093,12 +1142,11 @@ class CreateContext:
|
|||
Raises:
|
||||
CreatorError: When identifier is not known.
|
||||
"""
|
||||
|
||||
creator = self.creators.get(identifier)
|
||||
# Fake CreatorError (Could be maybe specific exception?)
|
||||
if creator is None:
|
||||
raise CreatorError(
|
||||
"Creator {} was not found".format(identifier)
|
||||
f"Creator {identifier} was not found"
|
||||
)
|
||||
return creator
|
||||
|
||||
|
|
@ -1147,7 +1195,7 @@ class CreateContext:
|
|||
)
|
||||
if folder_entity is None:
|
||||
raise CreatorError(
|
||||
"Folder '{}' was not found".format(folder_path)
|
||||
f"Folder '{folder_path}' was not found"
|
||||
)
|
||||
|
||||
if task_entity is None:
|
||||
|
|
@ -1233,7 +1281,7 @@ class CreateContext:
|
|||
raise CreatorsCreateFailed([fail_info])
|
||||
return result
|
||||
|
||||
def creator_removed_instance(self, instance: "CreatedInstance"):
|
||||
def creator_removed_instance(self, instance: CreatedInstance):
|
||||
"""When creator removes instance context should be acknowledged.
|
||||
|
||||
If creator removes instance context should know about it to avoid
|
||||
|
|
@ -1243,7 +1291,6 @@ class CreateContext:
|
|||
instance (CreatedInstance): Object of instance which was removed
|
||||
from scene metadata.
|
||||
"""
|
||||
|
||||
self._remove_instances([instance])
|
||||
|
||||
def add_convertor_item(self, convertor_identifier, label):
|
||||
|
|
@ -1424,7 +1471,6 @@ class CreateContext:
|
|||
ConvertorsFindFailed: When one or more convertors fails during
|
||||
finding.
|
||||
"""
|
||||
|
||||
self.convertor_items_by_id = {}
|
||||
|
||||
failed_info = []
|
||||
|
|
@ -1439,9 +1485,7 @@ class CreateContext:
|
|||
)
|
||||
)
|
||||
self.log.warning(
|
||||
"Failed to find instances of convertor \"{}\"".format(
|
||||
convertor.identifier
|
||||
),
|
||||
f'Failed to find instances of convertor "{convertor.identifier}"',
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
|
|
@ -1453,7 +1497,6 @@ class CreateContext:
|
|||
|
||||
Reset instances if any autocreator executed properly.
|
||||
"""
|
||||
|
||||
failed_info = []
|
||||
for creator in self.sorted_autocreators:
|
||||
identifier = creator.identifier
|
||||
|
|
@ -1474,10 +1517,7 @@ class CreateContext:
|
|||
Dict[str, Optional[Dict[str, Any]]]: Folder entities by path.
|
||||
|
||||
"""
|
||||
output = {
|
||||
folder_path: None
|
||||
for folder_path in folder_paths
|
||||
}
|
||||
output = dict.fromkeys(folder_paths)
|
||||
remainder_paths = set()
|
||||
for folder_path in output:
|
||||
# Skip invalid folder paths (folder name or empty path)
|
||||
|
|
@ -1649,7 +1689,7 @@ class CreateContext:
|
|||
return output.get(folder_path, {}).get(task_name)
|
||||
|
||||
def get_instances_folder_entities(
|
||||
self, instances: Optional[Iterable["CreatedInstance"]] = None
|
||||
self, instances: Optional[Iterable[CreatedInstance]] = None
|
||||
) -> Dict[str, Optional[Dict[str, Any]]]:
|
||||
if instances is None:
|
||||
instances = self._instances_by_id.values()
|
||||
|
|
@ -1673,7 +1713,7 @@ class CreateContext:
|
|||
return output
|
||||
|
||||
def get_instances_task_entities(
|
||||
self, instances: Optional[Iterable["CreatedInstance"]] = None
|
||||
self, instances: Optional[Iterable[CreatedInstance]] = None
|
||||
):
|
||||
"""Get task entities for instances.
|
||||
|
||||
|
|
@ -1719,7 +1759,7 @@ class CreateContext:
|
|||
return output
|
||||
|
||||
def get_instances_context_info(
|
||||
self, instances: Optional[Iterable["CreatedInstance"]] = None
|
||||
self, instances: Optional[Iterable[CreatedInstance]] = None
|
||||
) -> Dict[str, InstanceContextInfo]:
|
||||
"""Validate 'folder' and 'task' instance context.
|
||||
|
||||
|
|
@ -1894,7 +1934,7 @@ class CreateContext:
|
|||
if not instances_by_identifier:
|
||||
return
|
||||
|
||||
error_message = "Instances update of creator \"{}\" failed. {}"
|
||||
error_message = 'Instances update of creator "{}" failed. {}'
|
||||
failed_info = []
|
||||
|
||||
for creator in self.get_sorted_creators(
|
||||
|
|
@ -1967,7 +2007,7 @@ class CreateContext:
|
|||
|
||||
self._remove_instances(instances, sender)
|
||||
|
||||
error_message = "Instances removement of creator \"{}\" failed. {}"
|
||||
error_message = 'Instances removement of creator "{}" failed. {}'
|
||||
failed_info = []
|
||||
# Remove instances by creator plugin order
|
||||
for creator in self.get_sorted_creators(
|
||||
|
|
@ -2022,7 +2062,6 @@ class CreateContext:
|
|||
Raises:
|
||||
UnavailableSharedData: When called out of collection phase.
|
||||
"""
|
||||
|
||||
if self._collection_shared_data is None:
|
||||
raise UnavailableSharedData(
|
||||
"Accessed Collection shared data out of collection phase"
|
||||
|
|
@ -2037,7 +2076,6 @@ class CreateContext:
|
|||
Args:
|
||||
convertor_identifier (str): Identifier of convertor.
|
||||
"""
|
||||
|
||||
convertor = self.convertors_plugins.get(convertor_identifier)
|
||||
if convertor is not None:
|
||||
convertor.convert()
|
||||
|
|
@ -2055,7 +2093,6 @@ class CreateContext:
|
|||
Raises:
|
||||
ConvertorsConversionFailed: When one or more convertors fails.
|
||||
"""
|
||||
|
||||
failed_info = []
|
||||
for convertor_identifier in convertor_identifiers:
|
||||
try:
|
||||
|
|
@ -2068,9 +2105,7 @@ class CreateContext:
|
|||
)
|
||||
)
|
||||
self.log.warning(
|
||||
"Failed to convert instances of convertor \"{}\"".format(
|
||||
convertor_identifier
|
||||
),
|
||||
f'Failed to convert instances of convertor "{convertor_identifier}"',
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
|
|
@ -2101,7 +2136,7 @@ class CreateContext:
|
|||
def _create_with_unified_error(
|
||||
self, identifier, creator, *args, **kwargs
|
||||
):
|
||||
error_message = "Failed to run Creator with identifier \"{}\". {}"
|
||||
error_message = 'Failed to run Creator with identifier "{}". {}'
|
||||
|
||||
label = None
|
||||
add_traceback = False
|
||||
|
|
@ -2201,7 +2236,7 @@ class CreateContext:
|
|||
|
||||
def _bulk_add_instances_finished(
|
||||
self,
|
||||
instances_to_validate: List["CreatedInstance"],
|
||||
instances_to_validate: List[CreatedInstance],
|
||||
sender: Optional[str]
|
||||
):
|
||||
if not instances_to_validate:
|
||||
|
|
@ -2264,7 +2299,7 @@ class CreateContext:
|
|||
|
||||
def _bulk_remove_instances_finished(
|
||||
self,
|
||||
instances_to_remove: List["CreatedInstance"],
|
||||
instances_to_remove: List[CreatedInstance],
|
||||
sender: Optional[str]
|
||||
):
|
||||
if not instances_to_remove:
|
||||
|
|
|
|||
|
|
@ -1,32 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import copy
|
||||
"""Definition of creator plugins."""
|
||||
import collections
|
||||
from typing import TYPE_CHECKING, Optional, Dict, Any
|
||||
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional
|
||||
|
||||
from ayon_core.settings import get_project_settings
|
||||
from ayon_core.lib import Logger, get_version_from_path
|
||||
from ayon_core.pipeline.plugin_discover import (
|
||||
deregister_plugin,
|
||||
deregister_plugin_path,
|
||||
discover,
|
||||
register_plugin,
|
||||
register_plugin_path,
|
||||
deregister_plugin,
|
||||
deregister_plugin_path
|
||||
)
|
||||
from ayon_core.pipeline.staging_dir import get_staging_dir_info, StagingDir
|
||||
from ayon_core.pipeline.staging_dir import StagingDir, get_staging_dir_info
|
||||
from ayon_core.settings import get_project_settings
|
||||
|
||||
from .constants import DEFAULT_VARIANT_VALUE
|
||||
from .product_name import get_product_name
|
||||
from .utils import get_next_versions_for_instances
|
||||
|
||||
# Avoid cyclic imports
|
||||
from .legacy_create import LegacyCreator
|
||||
from .product_name import get_product_name
|
||||
from .structures import CreatedInstance
|
||||
from .utils import get_next_versions_for_instances
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ayon_core.lib import AbstractAttrDef
|
||||
# Avoid cyclic imports
|
||||
from .context import CreateContext, UpdateData # noqa: F401
|
||||
|
||||
from .context import CreateContext
|
||||
|
||||
|
||||
class ProductConvertorPlugin(ABC):
|
||||
|
|
@ -58,17 +60,17 @@ class ProductConvertorPlugin(ABC):
|
|||
|
||||
_log = None
|
||||
|
||||
def __init__(self, create_context):
|
||||
def __init__(self, create_context: CreateContext):
|
||||
"""Constructor of convertor plugin."""
|
||||
self._create_context = create_context
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
def log(self) -> logging.Logger:
|
||||
"""Logger of the plugin.
|
||||
|
||||
Returns:
|
||||
logging.Logger: Logger with name of the plugin.
|
||||
"""
|
||||
|
||||
if self._log is None:
|
||||
self._log = Logger.get_logger(self.__class__.__name__)
|
||||
return self._log
|
||||
|
|
@ -86,8 +88,6 @@ class ProductConvertorPlugin(ABC):
|
|||
str: Converted identifier unique for all converters in host.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def find_instances(self):
|
||||
"""Look for legacy instances in the scene.
|
||||
|
|
@ -96,14 +96,10 @@ class ProductConvertorPlugin(ABC):
|
|||
convert.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def convert(self):
|
||||
"""Conversion code."""
|
||||
|
||||
pass
|
||||
|
||||
@property
|
||||
def create_context(self):
|
||||
"""Quick access to create context.
|
||||
|
|
@ -111,7 +107,6 @@ class ProductConvertorPlugin(ABC):
|
|||
Returns:
|
||||
CreateContext: Context which initialized the plugin.
|
||||
"""
|
||||
|
||||
return self._create_context
|
||||
|
||||
@property
|
||||
|
|
@ -124,7 +119,6 @@ class ProductConvertorPlugin(ABC):
|
|||
Raises:
|
||||
UnavailableSharedData: When called out of collection phase.
|
||||
"""
|
||||
|
||||
return self._create_context.collection_shared_data
|
||||
|
||||
def add_convertor_item(self, label):
|
||||
|
|
@ -133,12 +127,10 @@ class ProductConvertorPlugin(ABC):
|
|||
Args:
|
||||
label (str): Label of item which will show in UI.
|
||||
"""
|
||||
|
||||
self._create_context.add_convertor_item(self.identifier, label)
|
||||
|
||||
def remove_convertor_item(self):
|
||||
"""Remove legacy item from create context when conversion finished."""
|
||||
|
||||
self._create_context.remove_convertor_item(self.identifier)
|
||||
|
||||
|
||||
|
|
@ -221,7 +213,6 @@ class BaseCreator(ABC):
|
|||
Returns:
|
||||
Optional[dict[str, Any]]: Settings values or None.
|
||||
"""
|
||||
|
||||
settings = project_settings.get(category_name)
|
||||
if not settings:
|
||||
return None
|
||||
|
|
@ -267,7 +258,6 @@ class BaseCreator(ABC):
|
|||
Args:
|
||||
project_settings (dict[str, Any]): Project settings.
|
||||
"""
|
||||
|
||||
settings_category = self.settings_category
|
||||
if not settings_category:
|
||||
return
|
||||
|
|
@ -279,18 +269,16 @@ class BaseCreator(ABC):
|
|||
project_settings, settings_category, settings_name
|
||||
)
|
||||
if settings is None:
|
||||
self.log.debug("No settings found for {}".format(cls_name))
|
||||
self.log.debug(f"No settings found for {cls_name}")
|
||||
return
|
||||
|
||||
for key, value in settings.items():
|
||||
# Log out attributes that are not defined on plugin object
|
||||
# - those may be potential dangerous typos in settings
|
||||
if not hasattr(self, key):
|
||||
self.log.debug((
|
||||
"Applying settings to unknown attribute '{}' on '{}'."
|
||||
).format(
|
||||
key, cls_name
|
||||
))
|
||||
self.log.debug(
|
||||
f"Applying settings to unknown attribute '{key}' on '{cls_name}'."
|
||||
)
|
||||
setattr(self, key, value)
|
||||
|
||||
def register_callbacks(self):
|
||||
|
|
@ -299,15 +287,13 @@ class BaseCreator(ABC):
|
|||
Default implementation does nothing. It can be overridden to register
|
||||
callbacks for creator.
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def identifier(self):
|
||||
"""Identifier of creator (must be unique).
|
||||
|
||||
Default implementation returns plugin's product type.
|
||||
Default implementation returns plugin's product base type.
|
||||
"""
|
||||
|
||||
return self.product_type
|
||||
|
||||
@property
|
||||
|
|
@ -315,8 +301,6 @@ class BaseCreator(ABC):
|
|||
def product_type(self):
|
||||
"""Family that plugin represents."""
|
||||
|
||||
pass
|
||||
|
||||
@property
|
||||
def project_name(self):
|
||||
"""Current project name.
|
||||
|
|
@ -324,7 +308,6 @@ class BaseCreator(ABC):
|
|||
Returns:
|
||||
str: Name of a project.
|
||||
"""
|
||||
|
||||
return self.create_context.project_name
|
||||
|
||||
@property
|
||||
|
|
@ -334,7 +317,6 @@ class BaseCreator(ABC):
|
|||
Returns:
|
||||
Anatomy: Project anatomy object.
|
||||
"""
|
||||
|
||||
return self.create_context.project_anatomy
|
||||
|
||||
@property
|
||||
|
|
@ -352,7 +334,6 @@ class BaseCreator(ABC):
|
|||
str: Group label that can be used for grouping of instances in UI.
|
||||
Group label can be overridden by instance itself.
|
||||
"""
|
||||
|
||||
if self._cached_group_label is None:
|
||||
label = self.identifier
|
||||
if self.group_label:
|
||||
|
|
@ -369,7 +350,6 @@ class BaseCreator(ABC):
|
|||
Returns:
|
||||
logging.Logger: Logger with name of the plugin.
|
||||
"""
|
||||
|
||||
if self._log is None:
|
||||
self._log = Logger.get_logger(self.__class__.__name__)
|
||||
return self._log
|
||||
|
|
@ -414,7 +394,6 @@ class BaseCreator(ABC):
|
|||
Args:
|
||||
instance (CreatedInstance): New created instance.
|
||||
"""
|
||||
|
||||
self.create_context.creator_adds_instance(instance)
|
||||
|
||||
def _remove_instance_from_context(self, instance):
|
||||
|
|
@ -427,7 +406,6 @@ class BaseCreator(ABC):
|
|||
Args:
|
||||
instance (CreatedInstance): Instance which should be removed.
|
||||
"""
|
||||
|
||||
self.create_context.creator_removed_instance(instance)
|
||||
|
||||
@abstractmethod
|
||||
|
|
@ -439,8 +417,6 @@ class BaseCreator(ABC):
|
|||
implementation
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def collect_instances(self):
|
||||
"""Collect existing instances related to this creator plugin.
|
||||
|
|
@ -466,8 +442,6 @@ class BaseCreator(ABC):
|
|||
```
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_instances(self, update_list):
|
||||
"""Store changes of existing instances so they can be recollected.
|
||||
|
|
@ -477,8 +451,6 @@ class BaseCreator(ABC):
|
|||
contain changed instance and it's changes.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def remove_instances(self, instances):
|
||||
"""Method called on instance removal.
|
||||
|
|
@ -491,14 +463,11 @@ class BaseCreator(ABC):
|
|||
removed.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def get_icon(self):
|
||||
"""Icon of creator (product type).
|
||||
|
||||
Can return path to image file or awesome icon name.
|
||||
"""
|
||||
|
||||
return self.icon
|
||||
|
||||
def get_dynamic_data(
|
||||
|
|
@ -514,7 +483,6 @@ class BaseCreator(ABC):
|
|||
|
||||
These may be dynamically created based on current context of workfile.
|
||||
"""
|
||||
|
||||
return {}
|
||||
|
||||
def get_product_name(
|
||||
|
|
@ -585,7 +553,7 @@ class BaseCreator(ABC):
|
|||
and values are stored to metadata for future usage and for publishing
|
||||
purposes.
|
||||
|
||||
NOTE:
|
||||
Note:
|
||||
Convert method should be implemented which should care about updating
|
||||
keys/values when plugin attributes change.
|
||||
|
||||
|
|
@ -593,7 +561,6 @@ class BaseCreator(ABC):
|
|||
list[AbstractAttrDef]: Attribute definitions that can be tweaked
|
||||
for created instance.
|
||||
"""
|
||||
|
||||
return self.instance_attr_defs
|
||||
|
||||
def get_attr_defs_for_instance(self, instance):
|
||||
|
|
@ -616,12 +583,10 @@ class BaseCreator(ABC):
|
|||
Raises:
|
||||
UnavailableSharedData: When called out of collection phase.
|
||||
"""
|
||||
|
||||
return self.create_context.collection_shared_data
|
||||
|
||||
def set_instance_thumbnail_path(self, instance_id, thumbnail_path=None):
|
||||
"""Set path to thumbnail for instance."""
|
||||
|
||||
self.create_context.thumbnail_paths_by_instance_id[instance_id] = (
|
||||
thumbnail_path
|
||||
)
|
||||
|
|
@ -642,7 +607,6 @@ class BaseCreator(ABC):
|
|||
Returns:
|
||||
dict[str, int]: Next versions by instance id.
|
||||
"""
|
||||
|
||||
return get_next_versions_for_instances(
|
||||
self.create_context.project_name, instances
|
||||
)
|
||||
|
|
@ -709,7 +673,6 @@ class Creator(BaseCreator):
|
|||
int: Order in which is creator shown (less == earlier). By default
|
||||
is using Creator's 'order' or processing.
|
||||
"""
|
||||
|
||||
return self.order
|
||||
|
||||
@abstractmethod
|
||||
|
|
@ -724,11 +687,9 @@ class Creator(BaseCreator):
|
|||
pre_create_data(dict): Data based on pre creation attributes.
|
||||
Those may affect how creator works.
|
||||
"""
|
||||
|
||||
# instance = CreatedInstance(
|
||||
# self.product_type, product_name, instance_data
|
||||
# )
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
"""Short description of product type and plugin.
|
||||
|
|
@ -736,7 +697,6 @@ class Creator(BaseCreator):
|
|||
Returns:
|
||||
str: Short description of product type.
|
||||
"""
|
||||
|
||||
return self.description
|
||||
|
||||
def get_detail_description(self):
|
||||
|
|
@ -747,7 +707,6 @@ class Creator(BaseCreator):
|
|||
Returns:
|
||||
str: Detailed description of product type for artist.
|
||||
"""
|
||||
|
||||
return self.detailed_description
|
||||
|
||||
def get_default_variants(self):
|
||||
|
|
@ -761,7 +720,6 @@ class Creator(BaseCreator):
|
|||
Returns:
|
||||
list[str]: Whisper variants for user input.
|
||||
"""
|
||||
|
||||
return copy.deepcopy(self.default_variants)
|
||||
|
||||
def get_default_variant(self, only_explicit=False):
|
||||
|
|
@ -781,7 +739,6 @@ class Creator(BaseCreator):
|
|||
Returns:
|
||||
str: Variant value.
|
||||
"""
|
||||
|
||||
if only_explicit or self._default_variant:
|
||||
return self._default_variant
|
||||
|
||||
|
|
@ -802,7 +759,6 @@ class Creator(BaseCreator):
|
|||
Returns:
|
||||
str: Variant value.
|
||||
"""
|
||||
|
||||
return self.get_default_variant()
|
||||
|
||||
def _set_default_variant_wrap(self, variant):
|
||||
|
|
@ -814,7 +770,6 @@ class Creator(BaseCreator):
|
|||
Args:
|
||||
variant (str): New default variant value.
|
||||
"""
|
||||
|
||||
self._default_variant = variant
|
||||
|
||||
default_variant = property(
|
||||
|
|
@ -964,7 +919,6 @@ class AutoCreator(BaseCreator):
|
|||
|
||||
def remove_instances(self, instances):
|
||||
"""Skip removal."""
|
||||
pass
|
||||
|
||||
|
||||
def discover_creator_plugins(*args, **kwargs):
|
||||
|
|
@ -988,9 +942,7 @@ def discover_legacy_creator_plugins():
|
|||
plugin.apply_settings(project_settings)
|
||||
except Exception:
|
||||
log.warning(
|
||||
"Failed to apply settings to creator {}".format(
|
||||
plugin.__name__
|
||||
),
|
||||
f"Failed to apply settings to creator {plugin.__name__}",
|
||||
exc_info=True
|
||||
)
|
||||
return plugins
|
||||
|
|
@ -1007,7 +959,6 @@ def get_legacy_creator_by_name(creator_name, case_sensitive=False):
|
|||
Returns:
|
||||
Creator: Return first matching plugin or `None`.
|
||||
"""
|
||||
|
||||
# Lower input creator name if is not case sensitive
|
||||
if not case_sensitive:
|
||||
creator_name = creator_name.lower()
|
||||
|
|
@ -1079,7 +1030,6 @@ def cache_and_get_instances(creator, shared_key, list_instances_func):
|
|||
dict[str, dict[str, Any]]: Cached instances by creator identifier from
|
||||
result of passed function.
|
||||
"""
|
||||
|
||||
if shared_key not in creator.collection_shared_data:
|
||||
value = collections.defaultdict(list)
|
||||
for instance in list_instances_func():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue