Merge branch 'develop' into enhancement/Loader-Delete-Old-Versions-action-confirmation

This commit is contained in:
Jakub Trllo 2024-07-15 17:02:32 +02:00 committed by GitHub
commit 310bb83ded
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 70 additions and 116 deletions

View file

@ -9,9 +9,8 @@ import logging
import threading import threading
import collections import collections
from uuid import uuid4 from uuid import uuid4
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
import appdirs import appdirs
import ayon_api import ayon_api
from semver import VersionInfo from semver import VersionInfo
@ -499,8 +498,7 @@ def is_func_marked(func):
return getattr(func, _MARKING_ATTR, False) return getattr(func, _MARKING_ATTR, False)
@six.add_metaclass(ABCMeta) class AYONAddon(ABC):
class AYONAddon(object):
"""Base class of AYON addon. """Base class of AYON addon.
Attributes: Attributes:

View file

@ -1,7 +1,5 @@
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
import six
from ayon_core import resources from ayon_core import resources
@ -15,8 +13,7 @@ class _AYONInterfaceMeta(ABCMeta):
return str(self) return str(self)
@six.add_metaclass(_AYONInterfaceMeta) class AYONInterface(metaclass=_AYONInterfaceMeta):
class AYONInterface:
"""Base class of Interface that can be used as Mixin with abstract parts. """Base class of Interface that can be used as Mixin with abstract parts.
This is way how AYON addon can define that contains specific predefined This is way how AYON addon can define that contains specific predefined

View file

@ -7,18 +7,15 @@ exists is used.
""" """
import os import os
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import platform import platform
import six
from ayon_core.lib import Logger from ayon_core.lib import Logger
from ayon_core.addon import AddonsManager from ayon_core.addon import AddonsManager
from ayon_core.settings import get_project_settings from ayon_core.settings import get_project_settings
@six.add_metaclass(ABCMeta) class HostDirmap(ABC):
class HostDirmap(object):
"""Abstract class for running dirmap on a workfile in a host. """Abstract class for running dirmap on a workfile in a host.
Dirmap is used to translate paths inside of host workfile from one Dirmap is used to translate paths inside of host workfile from one

View file

@ -1,15 +1,13 @@
import os import os
import logging import logging
import contextlib import contextlib
from abc import ABCMeta, abstractproperty from abc import ABC, abstractproperty
import six
# NOTE can't import 'typing' because of issues in Maya 2020 # NOTE can't import 'typing' because of issues in Maya 2020
# - shiboken crashes on 'typing' module import # - shiboken crashes on 'typing' module import
@six.add_metaclass(ABCMeta) class HostBase(ABC):
class HostBase(object):
"""Base of host implementation class. """Base of host implementation class.
Host is pipeline implementation of DCC application. This class should help Host is pipeline implementation of DCC application. This class should help

View file

@ -1,5 +1,4 @@
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
class MissingMethodsError(ValueError): class MissingMethodsError(ValueError):
@ -106,8 +105,7 @@ class ILoadHost:
return self.get_containers() return self.get_containers()
@six.add_metaclass(ABCMeta) class IWorkfileHost(ABC):
class IWorkfileHost:
"""Implementation requirements to be able use workfile utils and tool.""" """Implementation requirements to be able use workfile utils and tool."""
@staticmethod @staticmethod

View file

@ -6,7 +6,6 @@ import json
import copy import copy
from abc import ABCMeta, abstractmethod, abstractproperty from abc import ABCMeta, abstractmethod, abstractproperty
import six
import clique import clique
# Global variable which store attribute definitions by type # Global variable which store attribute definitions by type
@ -91,8 +90,7 @@ class AbstractAttrDefMeta(ABCMeta):
return obj return obj
@six.add_metaclass(AbstractAttrDefMeta) class AbstractAttrDef(metaclass=AbstractAttrDefMeta):
class AbstractAttrDef(object):
"""Abstraction of attribute definition. """Abstraction of attribute definition.
Each attribute definition must have implemented validation and Each attribute definition must have implemented validation and
@ -349,7 +347,7 @@ class NumberDef(AbstractAttrDef):
) )
def convert_value(self, value): def convert_value(self, value):
if isinstance(value, six.string_types): if isinstance(value, str):
try: try:
value = float(value) value = float(value)
except Exception: except Exception:
@ -396,12 +394,12 @@ class TextDef(AbstractAttrDef):
if multiline is None: if multiline is None:
multiline = False multiline = False
elif not isinstance(default, six.string_types): elif not isinstance(default, str):
raise TypeError(( raise TypeError((
"'default' argument must be a {}, not '{}'" f"'default' argument must be a str, not '{type(default)}'"
).format(six.string_types, type(default))) ))
if isinstance(regex, six.string_types): if isinstance(regex, str):
regex = re.compile(regex) regex = re.compile(regex)
self.multiline = multiline self.multiline = multiline
@ -418,7 +416,7 @@ class TextDef(AbstractAttrDef):
) )
def convert_value(self, value): def convert_value(self, value):
if isinstance(value, six.string_types): if isinstance(value, str):
return value return value
return self.default return self.default
@ -736,7 +734,7 @@ class FileDefItem(object):
else: else:
output.append(item) output.append(item)
elif isinstance(item, six.string_types): elif isinstance(item, str):
str_filepaths.append(item) str_filepaths.append(item)
else: else:
raise TypeError( raise TypeError(
@ -844,7 +842,7 @@ class FileDef(AbstractAttrDef):
if isinstance(default, dict): if isinstance(default, dict):
FileDefItem.from_dict(default) FileDefItem.from_dict(default)
elif isinstance(default, six.string_types): elif isinstance(default, str):
default = FileDefItem.from_paths([default.strip()])[0] default = FileDefItem.from_paths([default.strip()])[0]
else: else:
@ -883,14 +881,14 @@ class FileDef(AbstractAttrDef):
) )
def convert_value(self, value): def convert_value(self, value):
if isinstance(value, six.string_types) or isinstance(value, dict): if isinstance(value, (str, dict)):
value = [value] value = [value]
if isinstance(value, (tuple, list, set)): if isinstance(value, (tuple, list, set)):
string_paths = [] string_paths = []
dict_items = [] dict_items = []
for item in value: for item in value:
if isinstance(item, six.string_types): if isinstance(item, str):
string_paths.append(item.strip()) string_paths.append(item.strip())
elif isinstance(item, dict): elif isinstance(item, dict):
try: try:

View file

@ -2,7 +2,6 @@ import os
import logging import logging
import sys import sys
import errno import errno
import six
from ayon_core.lib import create_hard_link from ayon_core.lib import create_hard_link
@ -158,11 +157,13 @@ class FileTransaction(object):
def rollback(self): def rollback(self):
errors = 0 errors = 0
last_exc = None
# Rollback any transferred files # Rollback any transferred files
for path in self._transferred: for path in self._transferred:
try: try:
os.remove(path) os.remove(path)
except OSError: except OSError as exc:
last_exc = exc
errors += 1 errors += 1
self.log.error( self.log.error(
"Failed to rollback created file: {}".format(path), "Failed to rollback created file: {}".format(path),
@ -172,7 +173,8 @@ class FileTransaction(object):
for backup, original in self._backup_to_original.items(): for backup, original in self._backup_to_original.items():
try: try:
os.rename(backup, original) os.rename(backup, original)
except OSError: except OSError as exc:
last_exc = exc
errors += 1 errors += 1
self.log.error( self.log.error(
"Failed to restore original file: {} -> {}".format( "Failed to restore original file: {} -> {}".format(
@ -183,7 +185,7 @@ class FileTransaction(object):
self.log.error( self.log.error(
"{} errors occurred during rollback.".format(errors), "{} errors occurred during rollback.".format(errors),
exc_info=True) exc_info=True)
six.reraise(*sys.exc_info()) raise last_exc
@property @property
def transferred(self): def transferred(self):
@ -200,11 +202,9 @@ class FileTransaction(object):
try: try:
os.makedirs(dirname) os.makedirs(dirname)
except OSError as e: except OSError as e:
if e.errno == errno.EEXIST: if e.errno != errno.EEXIST:
pass
else:
self.log.critical("An unexpected error occurred.") self.log.critical("An unexpected error occurred.")
six.reraise(*sys.exc_info()) raise e
def _same_paths(self, src, dst): def _same_paths(self, src, dst):
# handles same paths but with C:/project vs c:/project # handles same paths but with C:/project vs c:/project

View file

@ -4,7 +4,7 @@ import os
import json import json
import platform import platform
from datetime import datetime from datetime import datetime
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
# disable lru cache in Python 2 # disable lru cache in Python 2
try: try:
@ -24,7 +24,6 @@ try:
except ImportError: except ImportError:
import ConfigParser as configparser import ConfigParser as configparser
import six
import appdirs import appdirs
import ayon_api import ayon_api
@ -133,8 +132,7 @@ class AYONSecureRegistry:
keyring.delete_password(self._name, name) keyring.delete_password(self._name, name)
@six.add_metaclass(ABCMeta) class ASettingRegistry(ABC):
class ASettingRegistry():
"""Abstract class defining structure of **SettingRegistry** class. """Abstract class defining structure of **SettingRegistry** class.
It is implementing methods to store secure items into keyring, otherwise It is implementing methods to store secure items into keyring, otherwise

View file

@ -2,8 +2,6 @@ import os
import re import re
import numbers import numbers
import six
KEY_PATTERN = re.compile(r"(\{.*?[^{0]*\})") KEY_PATTERN = re.compile(r"(\{.*?[^{0]*\})")
KEY_PADDING_PATTERN = re.compile(r"([^:]+)\S+[><]\S+") KEY_PADDING_PATTERN = re.compile(r"([^:]+)\S+[><]\S+")
SUB_DICT_PATTERN = re.compile(r"([^\[\]]+)") SUB_DICT_PATTERN = re.compile(r"([^\[\]]+)")
@ -14,7 +12,7 @@ class TemplateUnsolved(Exception):
"""Exception for unsolved template when strict is set to True.""" """Exception for unsolved template when strict is set to True."""
msg = "Template \"{0}\" is unsolved.{1}{2}" msg = "Template \"{0}\" is unsolved.{1}{2}"
invalid_types_msg = " Keys with invalid DataType: `{0}`." invalid_types_msg = " Keys with invalid data type: `{0}`."
missing_keys_msg = " Missing keys: \"{0}\"." missing_keys_msg = " Missing keys: \"{0}\"."
def __init__(self, template, missing_keys, invalid_types): def __init__(self, template, missing_keys, invalid_types):
@ -43,7 +41,7 @@ class TemplateUnsolved(Exception):
class StringTemplate(object): class StringTemplate(object):
"""String that can be formatted.""" """String that can be formatted."""
def __init__(self, template): def __init__(self, template):
if not isinstance(template, six.string_types): if not isinstance(template, str):
raise TypeError("<{}> argument must be a string, not {}.".format( raise TypeError("<{}> argument must be a string, not {}.".format(
self.__class__.__name__, str(type(template)) self.__class__.__name__, str(type(template))
)) ))
@ -63,7 +61,7 @@ class StringTemplate(object):
new_parts = [] new_parts = []
for part in parts: for part in parts:
if not isinstance(part, six.string_types): if not isinstance(part, str):
new_parts.append(part) new_parts.append(part)
continue continue
@ -113,7 +111,7 @@ class StringTemplate(object):
""" """
result = TemplatePartResult() result = TemplatePartResult()
for part in self._parts: for part in self._parts:
if isinstance(part, six.string_types): if isinstance(part, str):
result.add_output(part) result.add_output(part)
else: else:
part.format(data, result) part.format(data, result)
@ -176,7 +174,7 @@ class StringTemplate(object):
value = "<>" value = "<>"
elif ( elif (
len(parts) == 1 len(parts) == 1
and isinstance(parts[0], six.string_types) and isinstance(parts[0], str)
): ):
value = "<{}>".format(parts[0]) value = "<{}>".format(parts[0])
else: else:
@ -200,8 +198,9 @@ class StringTemplate(object):
new_parts.extend(tmp_parts[idx]) new_parts.extend(tmp_parts[idx])
return new_parts return new_parts
class TemplateResult(str): class TemplateResult(str):
"""Result of template format with most of information in. """Result of template format with most of the information in.
Args: Args:
used_values (dict): Dictionary of template filling data with used_values (dict): Dictionary of template filling data with
@ -299,7 +298,7 @@ class TemplatePartResult:
self._optional = True self._optional = True
def add_output(self, other): def add_output(self, other):
if isinstance(other, six.string_types): if isinstance(other, str):
self._output += other self._output += other
elif isinstance(other, TemplatePartResult): elif isinstance(other, TemplatePartResult):
@ -457,7 +456,7 @@ class FormattingPart:
return True return True
for inh_class in type(value).mro(): for inh_class in type(value).mro():
if inh_class in six.string_types: if inh_class is str:
return True return True
return False return False
@ -568,7 +567,7 @@ class OptionalPart:
def format(self, data, result): def format(self, data, result):
new_result = TemplatePartResult(True) new_result = TemplatePartResult(True)
for part in self._parts: for part in self._parts:
if isinstance(part, six.string_types): if isinstance(part, str):
new_result.add_output(part) new_result.add_output(part)
else: else:
part.format(data, new_result) part.format(data, new_result)

View file

@ -3,9 +3,7 @@ import copy
import collections import collections
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
from ayon_core.settings import get_project_settings from ayon_core.settings import get_project_settings
from ayon_core.lib import Logger from ayon_core.lib import Logger
@ -38,8 +36,7 @@ class CreatorError(Exception):
super(CreatorError, self).__init__(message) super(CreatorError, self).__init__(message)
@six.add_metaclass(ABCMeta) class ProductConvertorPlugin(ABC):
class ProductConvertorPlugin(object):
"""Helper for conversion of instances created using legacy creators. """Helper for conversion of instances created using legacy creators.
Conversion from legacy creators would mean to lose legacy instances, Conversion from legacy creators would mean to lose legacy instances,
@ -152,8 +149,7 @@ class ProductConvertorPlugin(object):
self._create_context.remove_convertor_item(self.identifier) self._create_context.remove_convertor_item(self.identifier)
@six.add_metaclass(ABCMeta) class BaseCreator(ABC):
class BaseCreator:
"""Plugin that create and modify instance data before publishing process. """Plugin that create and modify instance data before publishing process.
We should maybe find better name as creation is only one part of its logic We should maybe find better name as creation is only one part of its logic

View file

@ -2,8 +2,6 @@ import os
import re import re
import json import json
import six
from ayon_core.settings import get_project_settings from ayon_core.settings import get_project_settings
from ayon_core.lib import Logger from ayon_core.lib import Logger
@ -109,6 +107,6 @@ def get_project_basic_paths(project_name):
if not folder_structure: if not folder_structure:
return [] return []
if isinstance(folder_structure, six.string_types): if isinstance(folder_structure, str):
folder_structure = json.loads(folder_structure) folder_structure = json.loads(folder_structure)
return _list_path_items(folder_structure) return _list_path_items(folder_structure)

View file

@ -7,8 +7,6 @@ TODO: use @dataclass when times come.
from abc import abstractmethod from abc import abstractmethod
import attr import attr
import six
import pyblish.api import pyblish.api
from .publish_plugins import AbstractMetaContextPlugin from .publish_plugins import AbstractMetaContextPlugin
@ -122,8 +120,9 @@ class RenderInstance(object):
raise ValueError("both tiles X a Y sizes are set to 1") raise ValueError("both tiles X a Y sizes are set to 1")
@six.add_metaclass(AbstractMetaContextPlugin) class AbstractCollectRender(
class AbstractCollectRender(pyblish.api.ContextPlugin): pyblish.api.ContextPlugin, metaclass=AbstractMetaContextPlugin
):
"""Gather all publishable render layers from renderSetup.""" """Gather all publishable render layers from renderSetup."""
order = pyblish.api.CollectorOrder + 0.01 order = pyblish.api.CollectorOrder + 0.01

View file

@ -1,11 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Abstract ExpectedFile class definition.""" """Abstract ExpectedFile class definition."""
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
@six.add_metaclass(ABCMeta) class ExpectedFiles(ABC):
class ExpectedFiles:
"""Class grouping functionality for all supported renderers. """Class grouping functionality for all supported renderers.
Attributes: Attributes:

View file

@ -17,7 +17,6 @@ import json
import logging import logging
import jsonschema import jsonschema
import six
log_ = logging.getLogger(__name__) log_ = logging.getLogger(__name__)
@ -44,7 +43,7 @@ def validate(data, schema=None):
root, schema = data["schema"].rsplit(":", 1) root, schema = data["schema"].rsplit(":", 1)
if isinstance(schema, six.string_types): if isinstance(schema, str):
schema = _cache[schema + ".json"] schema = _cache[schema + ".json"]
resolver = jsonschema.RefResolver( resolver = jsonschema.RefResolver(

View file

@ -15,9 +15,8 @@ import os
import re import re
import collections import collections
import copy import copy
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
from ayon_api import ( from ayon_api import (
get_folders, get_folders,
get_folder_by_path, get_folder_by_path,
@ -82,8 +81,7 @@ class TemplateLoadFailed(Exception):
pass pass
@six.add_metaclass(ABCMeta) class AbstractTemplateBuilder(ABC):
class AbstractTemplateBuilder(object):
"""Abstraction of Template Builder. """Abstraction of Template Builder.
Builder cares about context, shared data, cache, discovery of plugins Builder cares about context, shared data, cache, discovery of plugins
@ -941,8 +939,7 @@ class AbstractTemplateBuilder(object):
) )
@six.add_metaclass(ABCMeta) class PlaceholderPlugin(ABC):
class PlaceholderPlugin(object):
"""Plugin which care about handling of placeholder items logic. """Plugin which care about handling of placeholder items logic.
Plugin create and update placeholders in scene and populate them on Plugin create and update placeholders in scene and populate them on

View file

@ -6,7 +6,6 @@ import platform
import shutil import shutil
import clique import clique
import six
import pyblish.api import pyblish.api
from ayon_core import resources, AYON_CORE_ROOT from ayon_core import resources, AYON_CORE_ROOT
@ -456,7 +455,7 @@ class ExtractBurnin(publish.Extractor):
sys_name = platform.system().lower() sys_name = platform.system().lower()
font_filepath = font_filepath.get(sys_name) font_filepath = font_filepath.get(sys_name)
if font_filepath and isinstance(font_filepath, six.string_types): if font_filepath and isinstance(font_filepath, str):
font_filepath = font_filepath.format(**os.environ) font_filepath = font_filepath.format(**os.environ)
if not os.path.exists(font_filepath): if not os.path.exists(font_filepath):
font_filepath = None font_filepath = None

View file

@ -4,9 +4,8 @@ import copy
import json import json
import shutil import shutil
import subprocess import subprocess
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
import clique import clique
import speedcopy import speedcopy
import pyblish.api import pyblish.api
@ -1661,8 +1660,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
return vf_back return vf_back
@six.add_metaclass(ABCMeta) class _OverscanValue(ABC):
class _OverscanValue:
def __repr__(self): def __repr__(self):
return "<{}> {}".format(self.__class__.__name__, str(self)) return "<{}> {}".format(self.__class__.__name__, str(self))

View file

@ -4,7 +4,6 @@ import sys
import copy import copy
import clique import clique
import six
import pyblish.api import pyblish.api
from ayon_api import ( from ayon_api import (
get_attributes_for_type, get_attributes_for_type,
@ -160,15 +159,14 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
# Raise DuplicateDestinationError as KnownPublishError # Raise DuplicateDestinationError as KnownPublishError
# and rollback the transactions # and rollback the transactions
file_transactions.rollback() file_transactions.rollback()
six.reraise(KnownPublishError, raise KnownPublishError(exc).with_traceback(sys.exc_info()[2])
KnownPublishError(exc),
sys.exc_info()[2]) except Exception as exc:
except Exception:
# clean destination # clean destination
# todo: preferably we'd also rollback *any* changes to the database # todo: preferably we'd also rollback *any* changes to the database
file_transactions.rollback() file_transactions.rollback()
self.log.critical("Error when registering", exc_info=True) self.log.critical("Error when registering", exc_info=True)
six.reraise(*sys.exc_info()) raise exc
# Finalizing can't rollback safely so no use for moving it to # Finalizing can't rollback safely so no use for moving it to
# the try, except. # the try, except.

View file

@ -2,7 +2,6 @@ import os
import copy import copy
import json import json
import collections import collections
import six
from ayon_core import resources from ayon_core import resources
@ -75,7 +74,7 @@ def _convert_color_values_to_objects(value):
output[_key] = _convert_color_values_to_objects(_value) output[_key] = _convert_color_values_to_objects(_value)
return output return output
if not isinstance(value, six.string_types): if not isinstance(value, str):
raise TypeError(( raise TypeError((
"Unexpected type in colors data '{}'. Expected 'str' or 'dict'." "Unexpected type in colors data '{}'. Expected 'str' or 'dict'."
).format(str(type(value)))) ).format(str(type(value))))

View file

@ -1,18 +1,16 @@
import time import time
import collections import collections
import contextlib import contextlib
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import ayon_api import ayon_api
import six
from ayon_core.lib import NestedCacheItem from ayon_core.lib import NestedCacheItem
HIERARCHY_MODEL_SENDER = "hierarchy.model" HIERARCHY_MODEL_SENDER = "hierarchy.model"
@six.add_metaclass(ABCMeta) class AbstractHierarchyController(ABC):
class AbstractHierarchyController:
@abstractmethod @abstractmethod
def emit_event(self, topic, data, source): def emit_event(self, topic, data, source):
pass pass

View file

@ -1,10 +1,7 @@
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
@six.add_metaclass(ABCMeta) class AbstractLauncherCommon(ABC):
class AbstractLauncherCommon(object):
@abstractmethod @abstractmethod
def register_event_callback(self, topic, callback): def register_event_callback(self, topic, callback):
"""Register event callback. """Register event callback.

View file

@ -1,5 +1,4 @@
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
from ayon_core.lib.attribute_definitions import ( from ayon_core.lib.attribute_definitions import (
AbstractAttrDef, AbstractAttrDef,
@ -347,8 +346,7 @@ class ActionItem:
return cls(**data) return cls(**data)
@six.add_metaclass(ABCMeta) class _BaseLoaderController(ABC):
class _BaseLoaderController(object):
"""Base loader controller abstraction. """Base loader controller abstraction.
Abstract base class that is required for both frontend and backed. Abstract base class that is required for both frontend and backed.

View file

@ -1,6 +1,5 @@
import os import os
import json import json
import six
import uuid import uuid
import appdirs import appdirs
@ -387,7 +386,7 @@ class LoadedFilesModel(QtGui.QStandardItemModel):
if not filepaths: if not filepaths:
return return
if isinstance(filepaths, six.string_types): if isinstance(filepaths, str):
filepaths = [filepaths] filepaths = [filepaths]
filtered_paths = [] filtered_paths = []

View file

@ -1,7 +1,6 @@
import os import os
from abc import ABCMeta, abstractmethod from abc import ABC, abstractmethod
import six
from ayon_core.style import get_default_entity_icon_color from ayon_core.style import get_default_entity_icon_color
@ -335,8 +334,7 @@ class WorkareaFilepathResult:
self.filepath = filepath self.filepath = filepath
@six.add_metaclass(ABCMeta) class AbstractWorkfilesCommon(ABC):
class AbstractWorkfilesCommon(object):
@abstractmethod @abstractmethod
def is_host_valid(self): def is_host_valid(self):
"""Host is valid for workfiles tool work. """Host is valid for workfiles tool work.