mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' of https://github.com/ynput/ayon-core into bugfix/AY-3059_Deadline-Allowed-env-keys
This commit is contained in:
commit
1bced2e13a
17 changed files with 387 additions and 325 deletions
|
|
@ -2,7 +2,7 @@ import os
|
|||
import json
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.maya.api.lib import extract_alembic
|
||||
from ayon_core.hosts.maya.api.alembic import extract_alembic
|
||||
|
||||
from maya import cmds
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import os
|
|||
from maya import cmds
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.maya.api.alembic import extract_alembic
|
||||
from ayon_core.hosts.maya.api.lib import (
|
||||
extract_alembic,
|
||||
suspended_refresh,
|
||||
maintained_selection,
|
||||
iter_visible_nodes_in_range
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import os
|
|||
from maya import cmds # noqa
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.maya.api.alembic import extract_alembic
|
||||
from ayon_core.hosts.maya.api.lib import (
|
||||
extract_alembic,
|
||||
suspended_refresh,
|
||||
maintained_selection
|
||||
)
|
||||
|
|
|
|||
|
|
@ -260,11 +260,11 @@ class UEProjectGenerationWorker(UEWorker):
|
|||
self.failed.emit(msg, return_code)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
# ensure we have PySide2 installed in engine
|
||||
# ensure we have PySide2/6 installed in engine
|
||||
|
||||
self.progress.emit(0)
|
||||
self.stage_begin.emit(
|
||||
(f"Checking PySide2 installation... {stage_count} "
|
||||
(f"Checking Qt bindings installation... {stage_count} "
|
||||
f" out of {stage_count}"))
|
||||
python_path = None
|
||||
if platform.system().lower() == "windows":
|
||||
|
|
@ -287,11 +287,30 @@ class UEProjectGenerationWorker(UEWorker):
|
|||
msg = f"Unreal Python not found at {python_path}"
|
||||
self.failed.emit(msg, 1)
|
||||
raise RuntimeError(msg)
|
||||
pyside_cmd = [python_path.as_posix(),
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"pyside2"]
|
||||
|
||||
pyside_version = "PySide2"
|
||||
ue_version = self.ue_version.split(".")
|
||||
if int(ue_version[0]) == 5 and int(ue_version[1]) >= 4:
|
||||
# Use PySide6 6.6.3 because 6.7.0 had a bug
|
||||
# - 'QPushButton' can't be added to 'QBoxLayout'
|
||||
pyside_version = "PySide6==6.6.3"
|
||||
|
||||
site_packages_prefix = python_path.parent.as_posix()
|
||||
|
||||
pyside_cmd = [
|
||||
python_path.as_posix(),
|
||||
"-m", "pip",
|
||||
"install",
|
||||
"--ignore-installed",
|
||||
pyside_version,
|
||||
|
||||
]
|
||||
|
||||
if platform.system().lower() == "windows":
|
||||
pyside_cmd += ["--target", site_packages_prefix]
|
||||
|
||||
print(f"--- Installing {pyside_version} ...")
|
||||
print(" ".join(pyside_cmd))
|
||||
|
||||
pyside_install = subprocess.Popen(pyside_cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
|
|
@ -306,8 +325,8 @@ class UEProjectGenerationWorker(UEWorker):
|
|||
return_code = pyside_install.wait()
|
||||
|
||||
if return_code and return_code != 0:
|
||||
msg = ("Failed to create the project! "
|
||||
"The installation of PySide2 has failed!")
|
||||
msg = (f"Failed to create the project! {return_code} "
|
||||
f"The installation of {pyside_version} has failed!: {pyside_install}")
|
||||
self.failed.emit(msg, return_code)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ from .local_settings import (
|
|||
get_openpype_username,
|
||||
)
|
||||
from .ayon_connection import initialize_ayon_connection
|
||||
from .cache import (
|
||||
CacheItem,
|
||||
NestedCacheItem,
|
||||
)
|
||||
from .events import (
|
||||
emit_event,
|
||||
register_event_callback
|
||||
|
|
@ -157,6 +161,9 @@ __all__ = [
|
|||
|
||||
"initialize_ayon_connection",
|
||||
|
||||
"CacheItem",
|
||||
"NestedCacheItem",
|
||||
|
||||
"emit_event",
|
||||
"register_event_callback",
|
||||
|
||||
|
|
|
|||
250
client/ayon_core/lib/cache.py
Normal file
250
client/ayon_core/lib/cache.py
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
import time
|
||||
import collections
|
||||
|
||||
InitInfo = collections.namedtuple(
|
||||
"InitInfo",
|
||||
["default_factory", "lifetime"]
|
||||
)
|
||||
|
||||
|
||||
def _default_factory_func():
|
||||
return None
|
||||
|
||||
|
||||
class CacheItem:
|
||||
"""Simple cache item with lifetime and default factory for default value.
|
||||
|
||||
Default factory should return default value that is used on init
|
||||
and on reset.
|
||||
|
||||
Args:
|
||||
default_factory (Optional[callable]): Function that returns default
|
||||
value used on init and on reset.
|
||||
lifetime (Optional[int]): Lifetime of the cache data in seconds.
|
||||
Default lifetime is 120 seconds.
|
||||
|
||||
"""
|
||||
def __init__(self, default_factory=None, lifetime=None):
|
||||
if lifetime is None:
|
||||
lifetime = 120
|
||||
self._lifetime = lifetime
|
||||
self._last_update = None
|
||||
if default_factory is None:
|
||||
default_factory = _default_factory_func
|
||||
self._default_factory = default_factory
|
||||
self._data = default_factory()
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
"""Is cache valid to use.
|
||||
|
||||
Return:
|
||||
bool: True if cache is valid, False otherwise.
|
||||
|
||||
"""
|
||||
if self._last_update is None:
|
||||
return False
|
||||
|
||||
return (time.time() - self._last_update) < self._lifetime
|
||||
|
||||
def set_lifetime(self, lifetime):
|
||||
"""Change lifetime of cache item.
|
||||
|
||||
Args:
|
||||
lifetime (int): Lifetime of the cache data in seconds.
|
||||
"""
|
||||
|
||||
self._lifetime = lifetime
|
||||
|
||||
def set_invalid(self):
|
||||
"""Set cache as invalid."""
|
||||
|
||||
self._last_update = None
|
||||
|
||||
def reset(self):
|
||||
"""Set cache as invalid and reset data."""
|
||||
|
||||
self._last_update = None
|
||||
self._data = self._default_factory()
|
||||
|
||||
def get_data(self):
|
||||
"""Receive cached data.
|
||||
|
||||
Returns:
|
||||
Any: Any data that are cached.
|
||||
|
||||
"""
|
||||
return self._data
|
||||
|
||||
def update_data(self, data):
|
||||
"""Update cache data.
|
||||
|
||||
Args:
|
||||
data (Any): Any data that are cached.
|
||||
|
||||
"""
|
||||
self._data = data
|
||||
self._last_update = time.time()
|
||||
|
||||
|
||||
class NestedCacheItem:
|
||||
"""Helper for cached items stored in nested structure.
|
||||
|
||||
Example:
|
||||
>>> cache = NestedCacheItem(levels=2, default_factory=lambda: 0)
|
||||
>>> cache["a"]["b"].is_valid
|
||||
False
|
||||
>>> cache["a"]["b"].get_data()
|
||||
0
|
||||
>>> cache["a"]["b"] = 1
|
||||
>>> cache["a"]["b"].is_valid
|
||||
True
|
||||
>>> cache["a"]["b"].get_data()
|
||||
1
|
||||
>>> cache.reset()
|
||||
>>> cache["a"]["b"].is_valid
|
||||
False
|
||||
|
||||
Args:
|
||||
levels (int): Number of nested levels where read cache is stored.
|
||||
default_factory (Optional[callable]): Function that returns default
|
||||
value used on init and on reset.
|
||||
lifetime (Optional[int]): Lifetime of the cache data in seconds.
|
||||
Default value is based on default value of 'CacheItem'.
|
||||
_init_info (Optional[InitInfo]): Private argument. Init info for
|
||||
nested cache where created from parent item.
|
||||
|
||||
"""
|
||||
def __init__(
|
||||
self, levels=1, default_factory=None, lifetime=None, _init_info=None
|
||||
):
|
||||
if levels < 1:
|
||||
raise ValueError("Nested levels must be greater than 0")
|
||||
self._data_by_key = {}
|
||||
if _init_info is None:
|
||||
_init_info = InitInfo(default_factory, lifetime)
|
||||
self._init_info = _init_info
|
||||
self._levels = levels
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Get cached data.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
|
||||
Returns:
|
||||
Union[NestedCacheItem, CacheItem]: Cache item.
|
||||
|
||||
"""
|
||||
cache = self._data_by_key.get(key)
|
||||
if cache is None:
|
||||
if self._levels > 1:
|
||||
cache = NestedCacheItem(
|
||||
levels=self._levels - 1,
|
||||
_init_info=self._init_info
|
||||
)
|
||||
else:
|
||||
cache = CacheItem(
|
||||
self._init_info.default_factory,
|
||||
self._init_info.lifetime
|
||||
)
|
||||
self._data_by_key[key] = cache
|
||||
return cache
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Update cached data.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
value (Any): Any data that are cached.
|
||||
|
||||
"""
|
||||
if self._levels > 1:
|
||||
raise AttributeError((
|
||||
"{} does not support '__setitem__'. Lower nested level by {}"
|
||||
).format(self.__class__.__name__, self._levels - 1))
|
||||
cache = self[key]
|
||||
cache.update_data(value)
|
||||
|
||||
def get(self, key):
|
||||
"""Get cached data.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
|
||||
Returns:
|
||||
Union[NestedCacheItem, CacheItem]: Cache item.
|
||||
|
||||
"""
|
||||
return self[key]
|
||||
|
||||
def cached_count(self):
|
||||
"""Amount of cached items.
|
||||
|
||||
Returns:
|
||||
int: Amount of cached items.
|
||||
|
||||
"""
|
||||
return len(self._data_by_key)
|
||||
|
||||
def clear_key(self, key):
|
||||
"""Clear cached item by key.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
|
||||
"""
|
||||
self._data_by_key.pop(key, None)
|
||||
|
||||
def clear_invalid(self):
|
||||
"""Clear all invalid cache items.
|
||||
|
||||
Note:
|
||||
To clear all cache items use 'reset'.
|
||||
|
||||
"""
|
||||
changed = {}
|
||||
children_are_nested = self._levels > 1
|
||||
for key, cache in tuple(self._data_by_key.items()):
|
||||
if children_are_nested:
|
||||
output = cache.clear_invalid()
|
||||
if output:
|
||||
changed[key] = output
|
||||
if not cache.cached_count():
|
||||
self._data_by_key.pop(key)
|
||||
elif not cache.is_valid:
|
||||
changed[key] = cache.get_data()
|
||||
self._data_by_key.pop(key)
|
||||
return changed
|
||||
|
||||
def reset(self):
|
||||
"""Reset cache.
|
||||
|
||||
Note:
|
||||
To clear only invalid cache items use 'clear_invalid'.
|
||||
|
||||
"""
|
||||
self._data_by_key = {}
|
||||
|
||||
def set_lifetime(self, lifetime):
|
||||
"""Change lifetime of all children cache items.
|
||||
|
||||
Args:
|
||||
lifetime (int): Lifetime of the cache data in seconds.
|
||||
|
||||
"""
|
||||
self._init_info.lifetime = lifetime
|
||||
for cache in self._data_by_key.values():
|
||||
cache.set_lifetime(lifetime)
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
"""Raise reasonable error when called on wrong level.
|
||||
|
||||
Raises:
|
||||
AttributeError: If called on nested cache item.
|
||||
|
||||
"""
|
||||
raise AttributeError((
|
||||
"{} does not support 'is_valid'. Lower nested level by '{}'"
|
||||
).format(self.__class__.__name__, self._levels))
|
||||
|
|
@ -3,11 +3,16 @@ import re
|
|||
import copy
|
||||
import platform
|
||||
import collections
|
||||
import time
|
||||
|
||||
import ayon_api
|
||||
|
||||
from ayon_core.lib import Logger, get_local_site_id, StringTemplate
|
||||
from ayon_core.lib import (
|
||||
Logger,
|
||||
get_local_site_id,
|
||||
StringTemplate,
|
||||
CacheItem,
|
||||
NestedCacheItem,
|
||||
)
|
||||
from ayon_core.addon import AddonsManager
|
||||
|
||||
from .exceptions import RootCombinationError, ProjectNotSet
|
||||
|
|
@ -397,62 +402,11 @@ class BaseAnatomy(object):
|
|||
)
|
||||
|
||||
|
||||
class CacheItem:
|
||||
"""Helper to cache data.
|
||||
|
||||
Helper does not handle refresh of data and does not mark data as outdated.
|
||||
Who uses the object should check of outdated state on his own will.
|
||||
"""
|
||||
|
||||
default_lifetime = 10
|
||||
|
||||
def __init__(self, lifetime=None):
|
||||
self._data = None
|
||||
self._cached = None
|
||||
self._lifetime = lifetime or self.default_lifetime
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"""Cached data/object.
|
||||
|
||||
Returns:
|
||||
Any: Whatever was cached.
|
||||
"""
|
||||
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def is_outdated(self):
|
||||
"""Item has outdated cache.
|
||||
|
||||
Lifetime of cache item expired or was not yet set.
|
||||
|
||||
Returns:
|
||||
bool: Item is outdated.
|
||||
"""
|
||||
|
||||
if self._cached is None:
|
||||
return True
|
||||
return (time.time() - self._cached) > self._lifetime
|
||||
|
||||
def update_data(self, data):
|
||||
"""Update cache of data.
|
||||
|
||||
Args:
|
||||
data (Any): Data to cache.
|
||||
"""
|
||||
|
||||
self._data = data
|
||||
self._cached = time.time()
|
||||
|
||||
|
||||
class Anatomy(BaseAnatomy):
|
||||
_sitesync_addon_cache = CacheItem()
|
||||
_project_cache = collections.defaultdict(CacheItem)
|
||||
_default_site_id_cache = collections.defaultdict(CacheItem)
|
||||
_root_overrides_cache = collections.defaultdict(
|
||||
lambda: collections.defaultdict(CacheItem)
|
||||
)
|
||||
_project_cache = NestedCacheItem(lifetime=10)
|
||||
_sitesync_addon_cache = CacheItem(lifetime=60)
|
||||
_default_site_id_cache = NestedCacheItem(lifetime=60)
|
||||
_root_overrides_cache = NestedCacheItem(2, lifetime=60)
|
||||
|
||||
def __init__(
|
||||
self, project_name=None, site_name=None, project_entity=None
|
||||
|
|
@ -477,18 +431,18 @@ class Anatomy(BaseAnatomy):
|
|||
@classmethod
|
||||
def get_project_entity_from_cache(cls, project_name):
|
||||
project_cache = cls._project_cache[project_name]
|
||||
if project_cache.is_outdated:
|
||||
if not project_cache.is_valid:
|
||||
project_cache.update_data(ayon_api.get_project(project_name))
|
||||
return copy.deepcopy(project_cache.data)
|
||||
return copy.deepcopy(project_cache.get_data())
|
||||
|
||||
@classmethod
|
||||
def get_sitesync_addon(cls):
|
||||
if cls._sitesync_addon_cache.is_outdated:
|
||||
if not cls._sitesync_addon_cache.is_valid:
|
||||
manager = AddonsManager()
|
||||
cls._sitesync_addon_cache.update_data(
|
||||
manager.get_enabled_addon("sitesync")
|
||||
)
|
||||
return cls._sitesync_addon_cache.data
|
||||
return cls._sitesync_addon_cache.get_data()
|
||||
|
||||
@classmethod
|
||||
def _get_studio_roots_overrides(cls, project_name):
|
||||
|
|
@ -533,14 +487,14 @@ class Anatomy(BaseAnatomy):
|
|||
elif not site_name:
|
||||
# Use sync server to receive active site name
|
||||
project_cache = cls._default_site_id_cache[project_name]
|
||||
if project_cache.is_outdated:
|
||||
if not project_cache.is_valid:
|
||||
project_cache.update_data(
|
||||
sitesync_addon.get_active_site_type(project_name)
|
||||
)
|
||||
site_name = project_cache.data
|
||||
site_name = project_cache.get_data()
|
||||
|
||||
site_cache = cls._root_overrides_cache[project_name][site_name]
|
||||
if site_cache.is_outdated:
|
||||
if not site_cache.is_valid:
|
||||
if site_name == "studio":
|
||||
# Handle studio root overrides without sync server
|
||||
# - studio root overrides can be done even without sync server
|
||||
|
|
@ -553,4 +507,4 @@ class Anatomy(BaseAnatomy):
|
|||
project_name, site_name
|
||||
)
|
||||
site_cache.update_data(roots_overrides)
|
||||
return site_cache.data
|
||||
return site_cache.get_data()
|
||||
|
|
|
|||
|
|
@ -1,239 +1,31 @@
|
|||
import time
|
||||
import collections
|
||||
import warnings
|
||||
|
||||
InitInfo = collections.namedtuple(
|
||||
"InitInfo",
|
||||
["default_factory", "lifetime"]
|
||||
from ayon_core.lib import CacheItem as _CacheItem
|
||||
from ayon_core.lib import NestedCacheItem as _NestedCacheItem
|
||||
|
||||
|
||||
# Cache classes were moved to `ayon_core.lib.cache`
|
||||
class CacheItem(_CacheItem):
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"Used 'CacheItem' from deprecated location "
|
||||
"'ayon_core.tools.common_models', use 'ayon_core.lib' instead.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class NestedCacheItem(_NestedCacheItem):
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"Used 'NestedCacheItem' from deprecated location "
|
||||
"'ayon_core.tools.common_models', use 'ayon_core.lib' instead.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"CacheItem",
|
||||
"NestedCacheItem",
|
||||
)
|
||||
|
||||
|
||||
def _default_factory_func():
|
||||
return None
|
||||
|
||||
|
||||
class CacheItem:
|
||||
"""Simple cache item with lifetime and default value.
|
||||
|
||||
Args:
|
||||
default_factory (Optional[callable]): Function that returns default
|
||||
value used on init and on reset.
|
||||
lifetime (Optional[int]): Lifetime of the cache data in seconds.
|
||||
"""
|
||||
|
||||
def __init__(self, default_factory=None, lifetime=None):
|
||||
if lifetime is None:
|
||||
lifetime = 120
|
||||
self._lifetime = lifetime
|
||||
self._last_update = None
|
||||
if default_factory is None:
|
||||
default_factory = _default_factory_func
|
||||
self._default_factory = default_factory
|
||||
self._data = default_factory()
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
"""Is cache valid to use.
|
||||
|
||||
Return:
|
||||
bool: True if cache is valid, False otherwise.
|
||||
"""
|
||||
|
||||
if self._last_update is None:
|
||||
return False
|
||||
|
||||
return (time.time() - self._last_update) < self._lifetime
|
||||
|
||||
def set_lifetime(self, lifetime):
|
||||
"""Change lifetime of cache item.
|
||||
|
||||
Args:
|
||||
lifetime (int): Lifetime of the cache data in seconds.
|
||||
"""
|
||||
|
||||
self._lifetime = lifetime
|
||||
|
||||
def set_invalid(self):
|
||||
"""Set cache as invalid."""
|
||||
|
||||
self._last_update = None
|
||||
|
||||
def reset(self):
|
||||
"""Set cache as invalid and reset data."""
|
||||
|
||||
self._last_update = None
|
||||
self._data = self._default_factory()
|
||||
|
||||
def get_data(self):
|
||||
"""Receive cached data.
|
||||
|
||||
Returns:
|
||||
Any: Any data that are cached.
|
||||
"""
|
||||
|
||||
return self._data
|
||||
|
||||
def update_data(self, data):
|
||||
self._data = data
|
||||
self._last_update = time.time()
|
||||
|
||||
|
||||
class NestedCacheItem:
|
||||
"""Helper for cached items stored in nested structure.
|
||||
|
||||
Example:
|
||||
>>> cache = NestedCacheItem(levels=2, default_factory=lambda: 0)
|
||||
>>> cache["a"]["b"].is_valid
|
||||
False
|
||||
>>> cache["a"]["b"].get_data()
|
||||
0
|
||||
>>> cache["a"]["b"] = 1
|
||||
>>> cache["a"]["b"].is_valid
|
||||
True
|
||||
>>> cache["a"]["b"].get_data()
|
||||
1
|
||||
>>> cache.reset()
|
||||
>>> cache["a"]["b"].is_valid
|
||||
False
|
||||
|
||||
Args:
|
||||
levels (int): Number of nested levels where read cache is stored.
|
||||
default_factory (Optional[callable]): Function that returns default
|
||||
value used on init and on reset.
|
||||
lifetime (Optional[int]): Lifetime of the cache data in seconds.
|
||||
_init_info (Optional[InitInfo]): Private argument. Init info for
|
||||
nested cache where created from parent item.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, levels=1, default_factory=None, lifetime=None, _init_info=None
|
||||
):
|
||||
if levels < 1:
|
||||
raise ValueError("Nested levels must be greater than 0")
|
||||
self._data_by_key = {}
|
||||
if _init_info is None:
|
||||
_init_info = InitInfo(default_factory, lifetime)
|
||||
self._init_info = _init_info
|
||||
self._levels = levels
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Get cached data.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
|
||||
Returns:
|
||||
Union[NestedCacheItem, CacheItem]: Cache item.
|
||||
"""
|
||||
|
||||
cache = self._data_by_key.get(key)
|
||||
if cache is None:
|
||||
if self._levels > 1:
|
||||
cache = NestedCacheItem(
|
||||
levels=self._levels - 1,
|
||||
_init_info=self._init_info
|
||||
)
|
||||
else:
|
||||
cache = CacheItem(
|
||||
self._init_info.default_factory,
|
||||
self._init_info.lifetime
|
||||
)
|
||||
self._data_by_key[key] = cache
|
||||
return cache
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Update cached data.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
value (Any): Any data that are cached.
|
||||
"""
|
||||
|
||||
if self._levels > 1:
|
||||
raise AttributeError((
|
||||
"{} does not support '__setitem__'. Lower nested level by {}"
|
||||
).format(self.__class__.__name__, self._levels - 1))
|
||||
cache = self[key]
|
||||
cache.update_data(value)
|
||||
|
||||
def get(self, key):
|
||||
"""Get cached data.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
|
||||
Returns:
|
||||
Union[NestedCacheItem, CacheItem]: Cache item.
|
||||
"""
|
||||
|
||||
return self[key]
|
||||
|
||||
def cached_count(self):
|
||||
"""Amount of cached items.
|
||||
|
||||
Returns:
|
||||
int: Amount of cached items.
|
||||
"""
|
||||
|
||||
return len(self._data_by_key)
|
||||
|
||||
def clear_key(self, key):
|
||||
"""Clear cached item by key.
|
||||
|
||||
Args:
|
||||
key (str): Key of the cache item.
|
||||
"""
|
||||
|
||||
self._data_by_key.pop(key, None)
|
||||
|
||||
def clear_invalid(self):
|
||||
"""Clear all invalid cache items.
|
||||
|
||||
Note:
|
||||
To clear all cache items use 'reset'.
|
||||
"""
|
||||
|
||||
changed = {}
|
||||
children_are_nested = self._levels > 1
|
||||
for key, cache in tuple(self._data_by_key.items()):
|
||||
if children_are_nested:
|
||||
output = cache.clear_invalid()
|
||||
if output:
|
||||
changed[key] = output
|
||||
if not cache.cached_count():
|
||||
self._data_by_key.pop(key)
|
||||
elif not cache.is_valid:
|
||||
changed[key] = cache.get_data()
|
||||
self._data_by_key.pop(key)
|
||||
return changed
|
||||
|
||||
def reset(self):
|
||||
"""Reset cache.
|
||||
|
||||
Note:
|
||||
To clear only invalid cache items use 'clear_invalid'.
|
||||
"""
|
||||
|
||||
self._data_by_key = {}
|
||||
|
||||
def set_lifetime(self, lifetime):
|
||||
"""Change lifetime of all children cache items.
|
||||
|
||||
Args:
|
||||
lifetime (int): Lifetime of the cache data in seconds.
|
||||
"""
|
||||
|
||||
self._init_info.lifetime = lifetime
|
||||
for cache in self._data_by_key.values():
|
||||
cache.set_lifetime(lifetime)
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
"""Raise reasonable error when called on wront level.
|
||||
|
||||
Raises:
|
||||
AttributeError: If called on nested cache item.
|
||||
"""
|
||||
|
||||
raise AttributeError((
|
||||
"{} does not support 'is_valid'. Lower nested level by '{}'"
|
||||
).format(self.__class__.__name__, self._levels))
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ import ayon_api
|
|||
import six
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
|
||||
from .cache import NestedCacheItem
|
||||
from ayon_core.lib import NestedCacheItem
|
||||
|
||||
HIERARCHY_MODEL_SENDER = "hierarchy.model"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import ayon_api
|
|||
import six
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
|
||||
from .cache import CacheItem
|
||||
from ayon_core.lib import CacheItem
|
||||
|
||||
PROJECTS_MODEL_SENDER = "projects.model"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import collections
|
|||
import ayon_api
|
||||
import appdirs
|
||||
|
||||
from .cache import NestedCacheItem
|
||||
from ayon_core.lib import NestedCacheItem
|
||||
|
||||
FileInfo = collections.namedtuple(
|
||||
"FileInfo",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import uuid
|
|||
|
||||
import ayon_api
|
||||
|
||||
from ayon_core.lib import NestedCacheItem
|
||||
from ayon_core.pipeline.load import (
|
||||
discover_loader_plugins,
|
||||
ProductLoaderPlugin,
|
||||
|
|
@ -17,7 +18,6 @@ from ayon_core.pipeline.load import (
|
|||
LoadError,
|
||||
IncompatibleLoaderError,
|
||||
)
|
||||
from ayon_core.tools.common_models import NestedCacheItem
|
||||
from ayon_core.tools.loader.abstract import ActionItem
|
||||
|
||||
ACTIONS_MODEL_SENDER = "actions.model"
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import arrow
|
|||
import ayon_api
|
||||
from ayon_api.operations import OperationsSession
|
||||
|
||||
from ayon_core.lib import NestedCacheItem
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.common_models import NestedCacheItem
|
||||
from ayon_core.tools.loader.abstract import (
|
||||
ProductTypeItem,
|
||||
ProductItem,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ import collections
|
|||
|
||||
from ayon_api import get_representations, get_versions_links
|
||||
|
||||
from ayon_core.lib import Logger
|
||||
from ayon_core.lib import Logger, NestedCacheItem
|
||||
from ayon_core.addon import AddonsManager
|
||||
from ayon_core.tools.common_models import NestedCacheItem
|
||||
from ayon_core.tools.loader.abstract import ActionItem
|
||||
|
||||
DOWNLOAD_IDENTIFIER = "sitesync.download"
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ line-ending = "auto"
|
|||
|
||||
[tool.codespell]
|
||||
# Ignore words that are not in the dictionary.
|
||||
ignore-words-list = "ayon,ynput,parms,parm,hda,developpement"
|
||||
ignore-words-list = "ayon,ynput,parms,parm,hda,developpement,ue"
|
||||
|
||||
skip = "./.*,./package/*,*/vendor/*,*/unreal/integration/*,*/aftereffects/api/extension/js/libs/*"
|
||||
count = true
|
||||
|
|
|
|||
|
|
@ -110,6 +110,26 @@ class ApplicationsAddon(AYONAddon, IPluginPaths):
|
|||
]
|
||||
}
|
||||
|
||||
def launch_application(
|
||||
self, app_name, project_name, folder_path, task_name
|
||||
):
|
||||
"""Launch application.
|
||||
|
||||
Args:
|
||||
app_name (str): Full application name e.g. 'maya/2024'.
|
||||
project_name (str): Project name.
|
||||
folder_path (str): Folder path.
|
||||
task_name (str): Task name.
|
||||
|
||||
"""
|
||||
app_manager = self.get_applications_manager()
|
||||
return app_manager.launch(
|
||||
app_name,
|
||||
project_name=project_name,
|
||||
folder_path=folder_path,
|
||||
task_name=task_name,
|
||||
)
|
||||
|
||||
# --- CLI ---
|
||||
def cli(self, addon_click_group):
|
||||
main_group = click_wrap.group(
|
||||
|
|
@ -134,6 +154,17 @@ class ApplicationsAddon(AYONAddon, IPluginPaths):
|
|||
default=None
|
||||
)
|
||||
)
|
||||
(
|
||||
main_group.command(
|
||||
self._cli_launch_applications,
|
||||
name="launch",
|
||||
help="Launch application"
|
||||
)
|
||||
.option("--app", required=True, help="Application name")
|
||||
.option("--project", required=True, help="Project name")
|
||||
.option("--folder", required=True, help="Folder path")
|
||||
.option("--task", required=True, help="Task name")
|
||||
)
|
||||
# Convert main command to click object and add it to parent group
|
||||
addon_click_group.add_command(
|
||||
main_group.to_click_obj()
|
||||
|
|
@ -171,3 +202,15 @@ class ApplicationsAddon(AYONAddon, IPluginPaths):
|
|||
|
||||
with open(output_json_path, "w") as file_stream:
|
||||
json.dump(env, file_stream, indent=4)
|
||||
|
||||
def _cli_launch_applications(self, project, folder, task, app):
|
||||
"""Launch application.
|
||||
|
||||
Args:
|
||||
project (str): Project name.
|
||||
folder (str): Folder path.
|
||||
task (str): Task name.
|
||||
app (str): Full application name e.g. 'maya/2024'.
|
||||
|
||||
"""
|
||||
self.launch_application(app, project, folder, task)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
name = "applications"
|
||||
title = "Applications"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
|
||||
ayon_server_version = ">=1.0.7"
|
||||
ayon_launcher_version = ">=1.0.2"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue