diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8af555adf2..c616b70e3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,20 @@
# Changelog
-## [3.14.3-nightly.5](https://github.com/pypeclub/OpenPype/tree/HEAD)
+## [3.14.4-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD)
-[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.2...HEAD)
+[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.3...HEAD)
+
+**🐛 Bug fixes**
+
+- Publisher: Files Drag n Drop cleanup [\#3888](https://github.com/pypeclub/OpenPype/pull/3888)
+
+**🔀 Refactored code**
+
+- General: import 'Logger' from 'openpype.lib' [\#3926](https://github.com/pypeclub/OpenPype/pull/3926)
+
+## [3.14.3](https://github.com/pypeclub/OpenPype/tree/3.14.3) (2022-10-03)
+
+[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.14.3-nightly.7...3.14.3)
**🚀 Enhancements**
@@ -16,13 +28,12 @@
- Flame: make migratable projects after creation [\#3860](https://github.com/pypeclub/OpenPype/pull/3860)
- Photoshop: synchronize image version with workfile [\#3854](https://github.com/pypeclub/OpenPype/pull/3854)
- General: Transcoding handle float2 attr type [\#3849](https://github.com/pypeclub/OpenPype/pull/3849)
-- General: Simple script for getting license information about used packages [\#3843](https://github.com/pypeclub/OpenPype/pull/3843)
-- Houdini: Increment current file on workfile publish [\#3840](https://github.com/pypeclub/OpenPype/pull/3840)
- General: Workfile template build enhancements [\#3838](https://github.com/pypeclub/OpenPype/pull/3838)
- General: lock task workfiles when they are working on [\#3810](https://github.com/pypeclub/OpenPype/pull/3810)
**🐛 Bug fixes**
+- Maya: Fix Render single camera validator [\#3929](https://github.com/pypeclub/OpenPype/pull/3929)
- Flame: loading multilayer exr to batch/reel is working [\#3901](https://github.com/pypeclub/OpenPype/pull/3901)
- Hiero: Fix inventory check on launch [\#3895](https://github.com/pypeclub/OpenPype/pull/3895)
- WebPublisher: Fix import after refactor [\#3891](https://github.com/pypeclub/OpenPype/pull/3891)
@@ -33,19 +44,18 @@
- Tray Publisher: skip plugin if otioTimeline is missing [\#3856](https://github.com/pypeclub/OpenPype/pull/3856)
- Flame: retimed attributes are integrated with settings [\#3855](https://github.com/pypeclub/OpenPype/pull/3855)
- Maya: Extract Playblast fix textures + labelize viewport show settings [\#3852](https://github.com/pypeclub/OpenPype/pull/3852)
-- Maya Deadline: Fix Tile Rendering by forcing integer pixel values [\#3758](https://github.com/pypeclub/OpenPype/pull/3758)
+- Maya: Publishing data key change [\#3811](https://github.com/pypeclub/OpenPype/pull/3811)
**🔀 Refactored code**
+- Maya: Remove unused 'openpype.api' imports in plugins [\#3925](https://github.com/pypeclub/OpenPype/pull/3925)
- Resolve: Use new Extractor location [\#3918](https://github.com/pypeclub/OpenPype/pull/3918)
- Unreal: Use new Extractor location [\#3917](https://github.com/pypeclub/OpenPype/pull/3917)
- Flame: Use new Extractor location [\#3916](https://github.com/pypeclub/OpenPype/pull/3916)
- Houdini: Use new Extractor location [\#3894](https://github.com/pypeclub/OpenPype/pull/3894)
- Harmony: Use new Extractor location [\#3893](https://github.com/pypeclub/OpenPype/pull/3893)
- Hiero: Use new Extractor location [\#3851](https://github.com/pypeclub/OpenPype/pull/3851)
-- Maya: Remove old legacy \(ftrack\) plug-ins that are of no use anymore [\#3819](https://github.com/pypeclub/OpenPype/pull/3819)
- Nuke: Use new Extractor location [\#3799](https://github.com/pypeclub/OpenPype/pull/3799)
-- Maya: Use new Extractor location [\#3775](https://github.com/pypeclub/OpenPype/pull/3775)
**Merged pull requests:**
@@ -57,10 +67,6 @@
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.14.2-nightly.5...3.14.2)
-**🆕 New features**
-
-- Nuke: Build workfile by template [\#3763](https://github.com/pypeclub/OpenPype/pull/3763)
-
**🚀 Enhancements**
- Flame: Adding Creator's retimed shot and handles switch [\#3826](https://github.com/pypeclub/OpenPype/pull/3826)
@@ -73,17 +79,14 @@
- General: Fix Pattern access in client code [\#3828](https://github.com/pypeclub/OpenPype/pull/3828)
- Launcher: Skip opening last work file works for groups [\#3822](https://github.com/pypeclub/OpenPype/pull/3822)
-- Maya: Publishing data key change [\#3811](https://github.com/pypeclub/OpenPype/pull/3811)
- Igniter: Fix status handling when version is already installed [\#3804](https://github.com/pypeclub/OpenPype/pull/3804)
- Resolve: Addon import is Python 2 compatible [\#3798](https://github.com/pypeclub/OpenPype/pull/3798)
-- Hiero: retimed clip publishing is working [\#3792](https://github.com/pypeclub/OpenPype/pull/3792)
- nuke: validate write node is not failing due wrong type [\#3780](https://github.com/pypeclub/OpenPype/pull/3780)
- Fix - changed format of version string in pyproject.toml [\#3777](https://github.com/pypeclub/OpenPype/pull/3777)
-- Ftrack status fix typo prgoress -\> progress [\#3761](https://github.com/pypeclub/OpenPype/pull/3761)
-- Fix version resolution [\#3757](https://github.com/pypeclub/OpenPype/pull/3757)
**🔀 Refactored code**
+- Maya: Remove old legacy \(ftrack\) plug-ins that are of no use anymore [\#3819](https://github.com/pypeclub/OpenPype/pull/3819)
- Photoshop: Use new Extractor location [\#3789](https://github.com/pypeclub/OpenPype/pull/3789)
- Blender: Use new Extractor location [\#3787](https://github.com/pypeclub/OpenPype/pull/3787)
- AfterEffects: Use new Extractor location [\#3784](https://github.com/pypeclub/OpenPype/pull/3784)
@@ -92,8 +95,6 @@
- General: Move queries of asset and representation links [\#3770](https://github.com/pypeclub/OpenPype/pull/3770)
- General: Move create project folders to pipeline [\#3768](https://github.com/pypeclub/OpenPype/pull/3768)
- General: Create project function moved to client code [\#3766](https://github.com/pypeclub/OpenPype/pull/3766)
-- Maya: Refactor submit deadline to use AbstractSubmitDeadline [\#3759](https://github.com/pypeclub/OpenPype/pull/3759)
-- General: Change publish template settings location [\#3755](https://github.com/pypeclub/OpenPype/pull/3755)
**Merged pull requests:**
@@ -104,18 +105,6 @@
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.14.1-nightly.4...3.14.1)
-**🚀 Enhancements**
-
-- General: Thumbnail can use project roots [\#3750](https://github.com/pypeclub/OpenPype/pull/3750)
-
-**🐛 Bug fixes**
-
-- Maya: Fix typo in getPanel argument `with\_focus` -\> `withFocus` [\#3753](https://github.com/pypeclub/OpenPype/pull/3753)
-
-**🔀 Refactored code**
-
-- General: Move delivery logic to pipeline [\#3751](https://github.com/pypeclub/OpenPype/pull/3751)
-
## [3.14.0](https://github.com/pypeclub/OpenPype/tree/3.14.0) (2022-08-18)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.14.0-nightly.1...3.14.0)
diff --git a/openpype/hosts/aftereffects/api/launch_logic.py b/openpype/hosts/aftereffects/api/launch_logic.py
index 30a3e1f1c3..9c8513fe8c 100644
--- a/openpype/hosts/aftereffects/api/launch_logic.py
+++ b/openpype/hosts/aftereffects/api/launch_logic.py
@@ -12,6 +12,7 @@ from wsrpc_aiohttp import (
from Qt import QtCore
+from openpype.lib import Logger
from openpype.pipeline import legacy_io
from openpype.tools.utils import host_tools
from openpype.tools.adobe_webserver.app import WebServerTool
@@ -84,8 +85,6 @@ class ProcessLauncher(QtCore.QObject):
@property
def log(self):
if self._log is None:
- from openpype.api import Logger
-
self._log = Logger.get_logger("{}-launcher".format(
self.route_name))
return self._log
diff --git a/openpype/hosts/aftereffects/api/pipeline.py b/openpype/hosts/aftereffects/api/pipeline.py
index c13c22ced5..7026fe3f05 100644
--- a/openpype/hosts/aftereffects/api/pipeline.py
+++ b/openpype/hosts/aftereffects/api/pipeline.py
@@ -4,8 +4,7 @@ from Qt import QtWidgets
import pyblish.api
-from openpype import lib
-from openpype.api import Logger
+from openpype.lib import Logger, register_event_callback
from openpype.pipeline import (
register_loader_plugin_path,
register_creator_plugin_path,
@@ -16,9 +15,8 @@ from openpype.pipeline import (
)
from openpype.pipeline.load import any_outdated_containers
import openpype.hosts.aftereffects
-from openpype.lib import register_event_callback
-from .launch_logic import get_stub
+from .launch_logic import get_stub, ConnectionNotEstablishedYet
log = Logger.get_logger(__name__)
@@ -111,7 +109,7 @@ def ls():
"""
try:
stub = get_stub() # only after AfterEffects is up
- except lib.ConnectionNotEstablishedYet:
+ except ConnectionNotEstablishedYet:
print("Not connected yet, ignoring")
return
@@ -284,7 +282,7 @@ def _get_stub():
"""
try:
stub = get_stub() # only after Photoshop is up
- except lib.ConnectionNotEstablishedYet:
+ except ConnectionNotEstablishedYet:
print("Not connected yet, ignoring")
return
diff --git a/openpype/hosts/blender/api/lib.py b/openpype/hosts/blender/api/lib.py
index 9cd1ace821..05912885f7 100644
--- a/openpype/hosts/blender/api/lib.py
+++ b/openpype/hosts/blender/api/lib.py
@@ -6,7 +6,7 @@ from typing import Dict, List, Union
import bpy
import addon_utils
-from openpype.api import Logger
+from openpype.lib import Logger
from . import pipeline
diff --git a/openpype/hosts/blender/api/pipeline.py b/openpype/hosts/blender/api/pipeline.py
index ea405b028e..c2aee1e653 100644
--- a/openpype/hosts/blender/api/pipeline.py
+++ b/openpype/hosts/blender/api/pipeline.py
@@ -20,8 +20,8 @@ from openpype.pipeline import (
deregister_creator_plugin_path,
AVALON_CONTAINER_ID,
)
-from openpype.api import Logger
from openpype.lib import (
+ Logger,
register_event_callback,
emit_event
)
diff --git a/openpype/hosts/celaction/api/cli.py b/openpype/hosts/celaction/api/cli.py
index eb91def090..88fc11cafb 100644
--- a/openpype/hosts/celaction/api/cli.py
+++ b/openpype/hosts/celaction/api/cli.py
@@ -6,9 +6,8 @@ import argparse
import pyblish.api
import pyblish.util
-from openpype.api import Logger
-import openpype
import openpype.hosts.celaction
+from openpype.lib import Logger
from openpype.hosts.celaction import api as celaction
from openpype.tools.utils import host_tools
from openpype.pipeline import install_openpype_plugins
diff --git a/openpype/hosts/flame/api/lib.py b/openpype/hosts/flame/api/lib.py
index b7f7b24e51..6aca5c5ce6 100644
--- a/openpype/hosts/flame/api/lib.py
+++ b/openpype/hosts/flame/api/lib.py
@@ -12,6 +12,9 @@ import xml.etree.cElementTree as cET
from copy import deepcopy, copy
from xml.etree import ElementTree as ET
from pprint import pformat
+
+from openpype.lib import Logger, run_subprocess
+
from .constants import (
MARKER_COLOR,
MARKER_DURATION,
@@ -20,9 +23,7 @@ from .constants import (
MARKER_PUBLISH_DEFAULT
)
-import openpype.api as openpype
-
-log = openpype.Logger.get_logger(__name__)
+log = Logger.get_logger(__name__)
FRAME_PATTERN = re.compile(r"[\._](\d+)[\.]")
@@ -1016,7 +1017,7 @@ class MediaInfoFile(object):
try:
# execute creation of clip xml template data
- openpype.run_subprocess(cmd_args)
+ run_subprocess(cmd_args)
except TypeError as error:
raise TypeError(
"Error creating `{}` due: {}".format(fpath, error))
diff --git a/openpype/hosts/flame/api/pipeline.py b/openpype/hosts/flame/api/pipeline.py
index 324d13bc3f..3a23389961 100644
--- a/openpype/hosts/flame/api/pipeline.py
+++ b/openpype/hosts/flame/api/pipeline.py
@@ -5,7 +5,7 @@ import os
import contextlib
from pyblish import api as pyblish
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.pipeline import (
register_loader_plugin_path,
register_creator_plugin_path,
diff --git a/openpype/hosts/flame/api/plugin.py b/openpype/hosts/flame/api/plugin.py
index 1a26e96c79..4bbdc79621 100644
--- a/openpype/hosts/flame/api/plugin.py
+++ b/openpype/hosts/flame/api/plugin.py
@@ -9,13 +9,14 @@ from Qt import QtCore, QtWidgets
import openpype.api as openpype
import qargparse
from openpype import style
+from openpype.lib import Logger
from openpype.pipeline import LegacyCreator, LoaderPlugin
from . import constants
from . import lib as flib
from . import pipeline as fpipeline
-log = openpype.Logger.get_logger(__name__)
+log = Logger.get_logger(__name__)
class CreatorWidget(QtWidgets.QDialog):
diff --git a/openpype/hosts/flame/api/render_utils.py b/openpype/hosts/flame/api/render_utils.py
index a29d6be695..7e50c2b23e 100644
--- a/openpype/hosts/flame/api/render_utils.py
+++ b/openpype/hosts/flame/api/render_utils.py
@@ -1,6 +1,6 @@
import os
from xml.etree import ElementTree as ET
-from openpype.api import Logger
+from openpype.lib import Logger
log = Logger.get_logger(__name__)
diff --git a/openpype/hosts/flame/api/utils.py b/openpype/hosts/flame/api/utils.py
index 2dfdfa8f48..fb8bdee42d 100644
--- a/openpype/hosts/flame/api/utils.py
+++ b/openpype/hosts/flame/api/utils.py
@@ -4,7 +4,7 @@ Flame utils for syncing scripts
import os
import shutil
-from openpype.api import Logger
+from openpype.lib import Logger
log = Logger.get_logger(__name__)
diff --git a/openpype/hosts/hiero/api/menu.py b/openpype/hosts/hiero/api/menu.py
index 541a1f1f92..2a7560c6ba 100644
--- a/openpype/hosts/hiero/api/menu.py
+++ b/openpype/hosts/hiero/api/menu.py
@@ -4,7 +4,7 @@ import sys
import hiero.core
from hiero.ui import findMenuAction
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.pipeline import legacy_io
from openpype.tools.utils import host_tools
diff --git a/openpype/hosts/hiero/api/tags.py b/openpype/hosts/hiero/api/tags.py
index 10df96fa53..fac26da03a 100644
--- a/openpype/hosts/hiero/api/tags.py
+++ b/openpype/hosts/hiero/api/tags.py
@@ -3,7 +3,7 @@ import os
import hiero
from openpype.client import get_project, get_assets
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.pipeline import legacy_io
log = Logger.get_logger(__name__)
diff --git a/openpype/hosts/hiero/api/workio.py b/openpype/hosts/hiero/api/workio.py
index 762e22804f..040fd1435a 100644
--- a/openpype/hosts/hiero/api/workio.py
+++ b/openpype/hosts/hiero/api/workio.py
@@ -1,7 +1,7 @@
import os
import hiero
-from openpype.api import Logger
+from openpype.lib import Logger
log = Logger.get_logger(__name__)
diff --git a/openpype/hosts/houdini/api/shelves.py b/openpype/hosts/houdini/api/shelves.py
index 248d99105c..3ccab964cd 100644
--- a/openpype/hosts/houdini/api/shelves.py
+++ b/openpype/hosts/houdini/api/shelves.py
@@ -1,7 +1,6 @@
import os
import logging
import platform
-import six
from openpype.settings import get_project_settings
@@ -9,16 +8,10 @@ import hou
log = logging.getLogger("openpype.hosts.houdini.shelves")
-if six.PY2:
- FileNotFoundError = IOError
-
def generate_shelves():
"""This function generates complete shelves from shelf set to tools
in Houdini from openpype project settings houdini shelf definition.
-
- Raises:
- FileNotFoundError: Raised when the shelf set filepath does not exist
"""
current_os = platform.system().lower()
@@ -27,51 +20,41 @@ def generate_shelves():
shelves_set_config = project_settings["houdini"]["shelves"]
if not shelves_set_config:
- log.debug(
- "No custom shelves found in project settings."
- )
+ log.debug("No custom shelves found in project settings.")
return
for shelf_set_config in shelves_set_config:
shelf_set_filepath = shelf_set_config.get('shelf_set_source_path')
+ shelf_set_os_filepath = shelf_set_filepath[current_os]
+ if shelf_set_os_filepath:
+ if not os.path.isfile(shelf_set_os_filepath):
+ log.error("Shelf path doesn't exist - "
+ "{}".format(shelf_set_os_filepath))
+ continue
- if shelf_set_filepath[current_os]:
- if not os.path.isfile(shelf_set_filepath[current_os]):
- raise FileNotFoundError(
- "This path doesn't exist - {}".format(
- shelf_set_filepath[current_os]
- )
- )
-
- hou.shelves.newShelfSet(file_path=shelf_set_filepath[current_os])
+ hou.shelves.newShelfSet(file_path=shelf_set_os_filepath)
continue
shelf_set_name = shelf_set_config.get('shelf_set_name')
if not shelf_set_name:
- log.warning(
- "No name found in shelf set definition."
- )
- return
-
- shelf_set = get_or_create_shelf_set(shelf_set_name)
+ log.warning("No name found in shelf set definition.")
+ continue
shelves_definition = shelf_set_config.get('shelf_definition')
-
if not shelves_definition:
log.debug(
"No shelf definition found for shelf set named '{}'".format(
shelf_set_name
)
)
- return
+ continue
+ shelf_set = get_or_create_shelf_set(shelf_set_name)
for shelf_definition in shelves_definition:
shelf_name = shelf_definition.get('shelf_name')
if not shelf_name:
- log.warning(
- "No name found in shelf definition."
- )
- return
+ log.warning("No name found in shelf definition.")
+ continue
shelf = get_or_create_shelf(shelf_name)
@@ -81,7 +64,7 @@ def generate_shelves():
shelf_name
)
)
- return
+ continue
mandatory_attributes = {'name', 'script'}
for tool_definition in shelf_definition.get('tools_list'):
@@ -91,14 +74,14 @@ def generate_shelves():
tool_definition[key] for key in mandatory_attributes
):
log.warning(
- "You need to specify at least the name and \
-the script path of the tool.")
+ "You need to specify at least the name and the "
+ "script path of the tool.")
continue
tool = get_or_create_tool(tool_definition, shelf)
if not tool:
- return
+ continue
# Add the tool to the shelf if not already in it
if tool not in shelf.tools():
@@ -121,12 +104,10 @@ def get_or_create_shelf_set(shelf_set_label):
"""
all_shelves_sets = hou.shelves.shelfSets().values()
- shelf_sets = [
- shelf for shelf in all_shelves_sets if shelf.label() == shelf_set_label
- ]
-
- if shelf_sets:
- return shelf_sets[0]
+ shelf_set = next((shelf for shelf in all_shelves_sets if
+ shelf.label() == shelf_set_label), None)
+ if shelf_set:
+ return shelf_set
shelf_set_name = shelf_set_label.replace(' ', '_').lower()
new_shelf_set = hou.shelves.newShelfSet(
@@ -148,10 +129,9 @@ def get_or_create_shelf(shelf_label):
"""
all_shelves = hou.shelves.shelves().values()
- shelf = [s for s in all_shelves if s.label() == shelf_label]
-
+ shelf = next((s for s in all_shelves if s.label() == shelf_label), None)
if shelf:
- return shelf[0]
+ return shelf
shelf_name = shelf_label.replace(' ', '_').lower()
new_shelf = hou.shelves.newShelf(
@@ -175,23 +155,21 @@ def get_or_create_tool(tool_definition, shelf):
existing_tools = shelf.tools()
tool_label = tool_definition.get('label')
- existing_tool = [
- tool for tool in existing_tools if tool.label() == tool_label
- ]
-
+ existing_tool = next(
+ (tool for tool in existing_tools if tool.label() == tool_label),
+ None
+ )
if existing_tool:
tool_definition.pop('name', None)
tool_definition.pop('label', None)
- existing_tool[0].setData(**tool_definition)
- return existing_tool[0]
+ existing_tool.setData(**tool_definition)
+ return existing_tool
tool_name = tool_label.replace(' ', '_').lower()
if not os.path.exists(tool_definition['script']):
log.warning(
- "This path doesn't exist - {}".format(
- tool_definition['script']
- )
+ "This path doesn't exist - {}".format(tool_definition['script'])
)
return
diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py
index 14aac2f206..b1ad3ca58e 100644
--- a/openpype/hosts/maya/plugins/publish/collect_render.py
+++ b/openpype/hosts/maya/plugins/publish/collect_render.py
@@ -102,23 +102,26 @@ class CollectMayaRender(pyblish.api.ContextPlugin):
}
for layer in collected_render_layers:
- try:
- if layer.startswith("LAYER_"):
- # this is support for legacy mode where render layers
- # started with `LAYER_` prefix.
- expected_layer_name = re.search(
- r"^LAYER_(.*)", layer).group(1)
- else:
- # new way is to prefix render layer name with instance
- # namespace.
- expected_layer_name = re.search(
- r"^.+:(.*)", layer).group(1)
- except IndexError:
+ if layer.startswith("LAYER_"):
+ # this is support for legacy mode where render layers
+ # started with `LAYER_` prefix.
+ layer_name_pattern = r"^LAYER_(.*)"
+ else:
+ # new way is to prefix render layer name with instance
+ # namespace.
+ layer_name_pattern = r"^.+:(.*)"
+
+ # todo: We should have a more explicit way to link the renderlayer
+ match = re.match(layer_name_pattern, layer)
+ if not match:
msg = "Invalid layer name in set [ {} ]".format(layer)
self.log.warning(msg)
continue
- self.log.info("processing %s" % layer)
+ expected_layer_name = match.group(1)
+ self.log.info("Processing '{}' as layer [ {} ]"
+ "".format(layer, expected_layer_name))
+
# check if layer is part of renderSetup
if expected_layer_name not in maya_render_layers:
msg = "Render layer [ {} ] is not in " "Render Setup".format(
diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py
index 2474b2ead6..ca44e98605 100644
--- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py
+++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py
@@ -268,14 +268,20 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
# go through definitions and test if such node.attribute exists.
# if so, compare its value from the one required.
for attr, value in OrderedDict(validation_settings).items():
- # first get node of that type
cls.log.debug("{}: {}".format(attr, value))
- node_type = attr.split(".")[0]
- attribute_name = ".".join(attr.split(".")[1:])
+ if "." not in attr:
+ cls.log.warning("Skipping invalid attribute defined in "
+ "validation settings: '{}'".format(attr))
+ continue
+
+ node_type, attribute_name = attr.split(".", 1)
+
+ # first get node of that type
nodes = cmds.ls(type=node_type)
- if not isinstance(nodes, list):
- cls.log.warning("No nodes of '{}' found.".format(node_type))
+ if not nodes:
+ cls.log.warning(
+ "No nodes of type '{}' found.".format(node_type))
continue
for node in nodes:
diff --git a/openpype/hosts/nuke/api/gizmo_menu.py b/openpype/hosts/nuke/api/gizmo_menu.py
index 0f1a3e03fc..9edfc62e3b 100644
--- a/openpype/hosts/nuke/api/gizmo_menu.py
+++ b/openpype/hosts/nuke/api/gizmo_menu.py
@@ -2,7 +2,7 @@ import os
import re
import nuke
-from openpype.api import Logger
+from openpype.lib import Logger
log = Logger.get_logger(__name__)
diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py
index e8fba8ae34..013b5e3ed4 100644
--- a/openpype/hosts/nuke/api/pipeline.py
+++ b/openpype/hosts/nuke/api/pipeline.py
@@ -14,10 +14,9 @@ from openpype.host import (
INewPublisher
)
from openpype.api import (
- Logger,
get_current_project_settings
)
-from openpype.lib import register_event_callback
+from openpype.lib import register_event_callback, Logger
from openpype.pipeline import (
register_loader_plugin_path,
register_creator_plugin_path,
diff --git a/openpype/hosts/nuke/plugins/inventory/repair_old_loaders.py b/openpype/hosts/nuke/plugins/inventory/repair_old_loaders.py
index c04c939a8d..764499ff0c 100644
--- a/openpype/hosts/nuke/plugins/inventory/repair_old_loaders.py
+++ b/openpype/hosts/nuke/plugins/inventory/repair_old_loaders.py
@@ -1,4 +1,4 @@
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.pipeline import InventoryAction
from openpype.hosts.nuke.api.lib import set_avalon_knob_data
diff --git a/openpype/hosts/photoshop/api/launch_logic.py b/openpype/hosts/photoshop/api/launch_logic.py
index 0bbb19523d..1f0203dca6 100644
--- a/openpype/hosts/photoshop/api/launch_logic.py
+++ b/openpype/hosts/photoshop/api/launch_logic.py
@@ -10,7 +10,7 @@ from wsrpc_aiohttp import (
from Qt import QtCore
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.pipeline import legacy_io
from openpype.tools.utils import host_tools
from openpype.tools.adobe_webserver.app import WebServerTool
diff --git a/openpype/hosts/photoshop/api/pipeline.py b/openpype/hosts/photoshop/api/pipeline.py
index f660096630..9f6fc0983c 100644
--- a/openpype/hosts/photoshop/api/pipeline.py
+++ b/openpype/hosts/photoshop/api/pipeline.py
@@ -3,8 +3,7 @@ from Qt import QtWidgets
import pyblish.api
-from openpype.api import Logger
-from openpype.lib import register_event_callback
+from openpype.lib import register_event_callback, Logger
from openpype.pipeline import (
legacy_io,
register_loader_plugin_path,
diff --git a/openpype/hosts/resolve/api/workio.py b/openpype/hosts/resolve/api/workio.py
index 5a742ecf7e..5ce73eea53 100644
--- a/openpype/hosts/resolve/api/workio.py
+++ b/openpype/hosts/resolve/api/workio.py
@@ -1,7 +1,7 @@
"""Host API required Work Files tool"""
import os
-from openpype.api import Logger
+from openpype.lib import Logger
from .lib import (
get_project_manager,
get_current_project,
diff --git a/openpype/hosts/traypublisher/plugins/create/create_from_settings.py b/openpype/hosts/traypublisher/plugins/create/create_from_settings.py
index 41c1c29bb0..5d80c20309 100644
--- a/openpype/hosts/traypublisher/plugins/create/create_from_settings.py
+++ b/openpype/hosts/traypublisher/plugins/create/create_from_settings.py
@@ -1,5 +1,6 @@
import os
-from openpype.api import get_project_settings, Logger
+from openpype.lib import Logger
+from openpype.api import get_project_settings
log = Logger.get_logger(__name__)
diff --git a/openpype/modules/ftrack/scripts/sub_event_status.py b/openpype/modules/ftrack/scripts/sub_event_status.py
index 3163642e3f..6c7ecb8351 100644
--- a/openpype/modules/ftrack/scripts/sub_event_status.py
+++ b/openpype/modules/ftrack/scripts/sub_event_status.py
@@ -15,8 +15,8 @@ from openpype_modules.ftrack.ftrack_server.lib import (
TOPIC_STATUS_SERVER,
TOPIC_STATUS_SERVER_RESULT
)
-from openpype.api import Logger
from openpype.lib import (
+ Logger,
is_current_version_studio_latest,
is_running_from_build,
get_expected_version,
diff --git a/openpype/modules/ftrack/scripts/sub_event_storer.py b/openpype/modules/ftrack/scripts/sub_event_storer.py
index 204cce89e8..a7e77951af 100644
--- a/openpype/modules/ftrack/scripts/sub_event_storer.py
+++ b/openpype/modules/ftrack/scripts/sub_event_storer.py
@@ -17,10 +17,10 @@ from openpype_modules.ftrack.ftrack_server.lib import (
)
from openpype_modules.ftrack.lib import get_ftrack_event_mongo_info
from openpype.lib import (
+ Logger,
get_openpype_version,
get_build_version
)
-from openpype.api import Logger
log = Logger.get_logger("Event storer")
subprocess_started = datetime.datetime.now()
diff --git a/openpype/modules/log_viewer/log_view_module.py b/openpype/modules/log_viewer/log_view_module.py
index 14be6b392e..da1628b71f 100644
--- a/openpype/modules/log_viewer/log_view_module.py
+++ b/openpype/modules/log_viewer/log_view_module.py
@@ -1,4 +1,3 @@
-from openpype.api import Logger
from openpype.modules import OpenPypeModule
from openpype_interfaces import ITrayModule
diff --git a/openpype/modules/sync_server/providers/local_drive.py b/openpype/modules/sync_server/providers/local_drive.py
index 01bc891d08..8f55dc529b 100644
--- a/openpype/modules/sync_server/providers/local_drive.py
+++ b/openpype/modules/sync_server/providers/local_drive.py
@@ -4,7 +4,7 @@ import shutil
import threading
import time
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.pipeline import Anatomy
from .abstract_provider import AbstractProvider
diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py
index 5b0532c60a..945a97a99c 100644
--- a/openpype/pipeline/create/creator_plugins.py
+++ b/openpype/pipeline/create/creator_plugins.py
@@ -9,7 +9,7 @@ from abc import (
import six
from openpype.settings import get_system_settings, get_project_settings
-from .subset_name import get_subset_name
+from openpype.lib import Logger
from openpype.pipeline.plugin_discover import (
discover,
register_plugin,
@@ -18,6 +18,7 @@ from openpype.pipeline.plugin_discover import (
deregister_plugin_path
)
+from .subset_name import get_subset_name
from .legacy_create import LegacyCreator
@@ -143,8 +144,6 @@ class BaseCreator:
"""
if self._log is None:
- from openpype.api import Logger
-
self._log = Logger.get_logger(self.__class__.__name__)
return self._log
diff --git a/openpype/pipeline/plugin_discover.py b/openpype/pipeline/plugin_discover.py
index 004e530b1c..7edd9ac290 100644
--- a/openpype/pipeline/plugin_discover.py
+++ b/openpype/pipeline/plugin_discover.py
@@ -2,7 +2,7 @@ import os
import inspect
import traceback
-from openpype.api import Logger
+from openpype.lib import Logger
from openpype.lib.python_module_tools import (
modules_from_path,
classes_from_module,
diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json
index cdf829db57..1517983569 100644
--- a/openpype/settings/defaults/project_settings/houdini.json
+++ b/openpype/settings/defaults/project_settings/houdini.json
@@ -1,15 +1,5 @@
{
- "shelves": [
- {
- "shelf_set_name": "OpenPype Shelves",
- "shelf_set_source_path": {
- "windows": "",
- "darwin": "",
- "linux": ""
- },
- "shelf_definition": []
- }
- ],
+ "shelves": [],
"create": {
"CreateArnoldAss": {
"enabled": true,
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json
index 6ee02ca78f..0cbb684fc6 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json
@@ -140,7 +140,7 @@
},
{
"type": "label",
- "label": "Add additional options - put attribute and value, like AASamples"
+ "label": "Add additional options - put attribute and value, like defaultArnoldRenderOptions.AASamples = 4"
},
{
"type": "dict-modifiable",
@@ -276,7 +276,7 @@
},
{
"type": "label",
- "label": "Add additional options - put attribute and value, like aaFilterSize"
+ "label": "Add additional options - put attribute and value, like vraySettings.aaFilterSize = 1.5"
},
{
"type": "dict-modifiable",
@@ -405,7 +405,7 @@
},
{
"type": "label",
- "label": "Add additional options - put attribute and value, like reflectionMaxTraceDepth"
+ "label": "Add additional options - put attribute and value, like redshiftOptions.reflectionMaxTraceDepth = 3"
},
{
"type": "dict-modifiable",
diff --git a/openpype/tools/launcher/actions.py b/openpype/tools/launcher/actions.py
index 546bda1c34..b954110da4 100644
--- a/openpype/tools/launcher/actions.py
+++ b/openpype/tools/launcher/actions.py
@@ -4,8 +4,9 @@ from Qt import QtWidgets, QtGui
from openpype import PLUGINS_DIR
from openpype import style
-from openpype.api import Logger, resources
+from openpype.api import resources
from openpype.lib import (
+ Logger,
ApplictionExecutableNotFound,
ApplicationLaunchFailed
)
diff --git a/openpype/tools/settings/local_settings/window.py b/openpype/tools/settings/local_settings/window.py
index 6a2db3fff5..761b978ab4 100644
--- a/openpype/tools/settings/local_settings/window.py
+++ b/openpype/tools/settings/local_settings/window.py
@@ -1,4 +1,3 @@
-import logging
from Qt import QtWidgets, QtGui
from openpype import style
@@ -7,10 +6,10 @@ from openpype.settings.lib import (
get_local_settings,
save_local_settings
)
+from openpype.lib import Logger
from openpype.tools.settings import CHILD_OFFSET
from openpype.tools.utils import MessageOverlayObject
from openpype.api import (
- Logger,
SystemSettings,
ProjectSettings
)
diff --git a/openpype/tools/standalonepublish/widgets/widget_components.py b/openpype/tools/standalonepublish/widgets/widget_components.py
index b3280089c3..237e1da583 100644
--- a/openpype/tools/standalonepublish/widgets/widget_components.py
+++ b/openpype/tools/standalonepublish/widgets/widget_components.py
@@ -6,9 +6,10 @@ import string
from Qt import QtWidgets, QtCore
-from openpype.api import execute, Logger
from openpype.pipeline import legacy_io
from openpype.lib import (
+ execute,
+ Logger,
get_openpype_execute_args,
apply_project_environments_value
)
diff --git a/openpype/tools/stdout_broker/app.py b/openpype/tools/stdout_broker/app.py
index a42d93dab4..f8dc2111aa 100644
--- a/openpype/tools/stdout_broker/app.py
+++ b/openpype/tools/stdout_broker/app.py
@@ -6,8 +6,8 @@ import websocket
import json
from datetime import datetime
+from openpype.lib import Logger
from openpype_modules.webserver.host_console_listener import MsgAction
-from openpype.api import Logger
log = Logger.get_logger(__name__)
diff --git a/openpype/tools/utils/host_tools.py b/openpype/tools/utils/host_tools.py
index d2f05d3302..552ce0d432 100644
--- a/openpype/tools/utils/host_tools.py
+++ b/openpype/tools/utils/host_tools.py
@@ -7,6 +7,7 @@ import os
import pyblish.api
from openpype.host import IWorkfileHost, ILoadHost
+from openpype.lib import Logger
from openpype.pipeline import (
registered_host,
legacy_io,
@@ -23,6 +24,7 @@ class HostToolsHelper:
Class may also contain tools that are available only for one or few hosts.
"""
+
def __init__(self, parent=None):
self._log = None
# Global parent for all tools (may and may not be set)
@@ -42,8 +44,6 @@ class HostToolsHelper:
@property
def log(self):
if self._log is None:
- from openpype.api import Logger
-
self._log = Logger.get_logger(self.__class__.__name__)
return self._log
diff --git a/openpype/tools/utils/lib.py b/openpype/tools/utils/lib.py
index fe7dda454b..31ea26cef9 100644
--- a/openpype/tools/utils/lib.py
+++ b/openpype/tools/utils/lib.py
@@ -16,11 +16,8 @@ from openpype.style import (
get_objected_colors,
)
from openpype.resources import get_image_path
-from openpype.lib import filter_profiles
-from openpype.api import (
- get_project_settings,
- Logger
-)
+from openpype.lib import filter_profiles, Logger
+from openpype.api import get_project_settings
from openpype.pipeline import registered_host
log = Logger.get_logger(__name__)
diff --git a/openpype/version.py b/openpype/version.py
index 18ff49ffbf..50864c0f1c 100644
--- a/openpype/version.py
+++ b/openpype/version.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
-__version__ = "3.14.3-nightly.5"
+__version__ = "3.14.4-nightly.1"
diff --git a/openpype/widgets/attribute_defs/files_widget.py b/openpype/widgets/attribute_defs/files_widget.py
index d29aa1b607..259cb774b0 100644
--- a/openpype/widgets/attribute_defs/files_widget.py
+++ b/openpype/widgets/attribute_defs/files_widget.py
@@ -138,11 +138,13 @@ class DropEmpty(QtWidgets.QWidget):
allowed_items = [item + "s" for item in allowed_items]
if not allowed_items:
+ self._drop_label_widget.setVisible(False)
self._items_label_widget.setText(
"It is not allowed to add anything here!"
)
return
+ self._drop_label_widget.setVisible(True)
items_label = "Multiple "
if self._single_item:
items_label = "Single "
@@ -235,10 +237,41 @@ class FilesModel(QtGui.QStandardItemModel):
self._filenames_by_dirpath = collections.defaultdict(set)
self._items_by_dirpath = collections.defaultdict(list)
+ self.rowsAboutToBeRemoved.connect(self._on_about_to_be_removed)
+ self.rowsInserted.connect(self._on_insert)
+
@property
def id(self):
return self._id
+ def _on_about_to_be_removed(self, parent_index, start, end):
+ """Make sure that removed items are removed from items mapping.
+
+ Connected with '_on_insert'. When user drag item and drop it to same
+ view the item is actually removed and creted again but it happens in
+ inner calls of Qt.
+ """
+
+ for row in range(start, end + 1):
+ index = self.index(row, 0, parent_index)
+ item_id = index.data(ITEM_ID_ROLE)
+ if item_id is not None:
+ self._items_by_id.pop(item_id, None)
+
+ def _on_insert(self, parent_index, start, end):
+ """Make sure new added items are stored in items mapping.
+
+ Connected to '_on_about_to_be_removed'. Some items are not created
+ using '_create_item' but are recreated using Qt. So the item is not in
+ mapping and if it would it would not lead to same item pointer.
+ """
+
+ for row in range(start, end + 1):
+ index = self.index(start, end, parent_index)
+ item_id = index.data(ITEM_ID_ROLE)
+ if item_id not in self._items_by_id:
+ self._items_by_id[item_id] = self.item(row)
+
def set_multivalue(self, multivalue):
"""Disable filtering."""
@@ -352,6 +385,10 @@ class FilesModel(QtGui.QStandardItemModel):
src_item_id = index.data(ITEM_ID_ROLE)
src_item = self._items_by_id.get(src_item_id)
+ src_row = None
+ if src_item:
+ src_row = src_item.row()
+
# Take out items that should be moved
items = []
for item_id in item_ids:
@@ -365,10 +402,12 @@ class FilesModel(QtGui.QStandardItemModel):
return False
# Calculate row where items should be inserted
- if src_item:
- src_row = src_item.row()
- else:
- src_row = root.rowCount()
+ row_count = root.rowCount()
+ if src_row is None:
+ src_row = row_count
+
+ if src_row > row_count:
+ src_row = row_count
root.insertRow(src_row, items)
return True
@@ -592,6 +631,13 @@ class FilesView(QtWidgets.QListView):
self._remove_btn.setVisible(not multivalue)
+ def update_remove_btn_visibility(self):
+ model = self.model()
+ visible = False
+ if model:
+ visible = model.rowCount() > 0
+ self._remove_btn.setVisible(visible)
+
def has_selected_item_ids(self):
"""Is any index selected."""
for index in self.selectionModel().selectedIndexes():
@@ -655,6 +701,7 @@ class FilesView(QtWidgets.QListView):
def showEvent(self, event):
super(FilesView, self).showEvent(event)
self._update_remove_btn()
+ self.update_remove_btn_visibility()
class FilesWidget(QtWidgets.QFrame):
@@ -673,12 +720,13 @@ class FilesWidget(QtWidgets.QFrame):
files_proxy_model.setSourceModel(files_model)
files_view = FilesView(self)
files_view.setModel(files_proxy_model)
- files_view.setVisible(False)
- layout = QtWidgets.QHBoxLayout(self)
+ layout = QtWidgets.QStackedLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
- layout.addWidget(empty_widget, 1)
- layout.addWidget(files_view, 1)
+ layout.setStackingMode(layout.StackAll)
+ layout.addWidget(empty_widget)
+ layout.addWidget(files_view)
+ layout.setCurrentWidget(empty_widget)
files_proxy_model.rowsInserted.connect(self._on_rows_inserted)
files_proxy_model.rowsRemoved.connect(self._on_rows_removed)
@@ -698,6 +746,8 @@ class FilesWidget(QtWidgets.QFrame):
self._widgets_by_id = {}
+ self._layout = layout
+
def _set_multivalue(self, multivalue):
if self._multivalue == multivalue:
return
@@ -774,6 +824,8 @@ class FilesWidget(QtWidgets.QFrame):
if not self._in_set_value:
self.value_changed.emit()
+ self._update_visibility()
+
def _on_rows_removed(self, parent_index, start_row, end_row):
available_item_ids = set()
for row in range(self._files_proxy_model.rowCount()):
@@ -793,6 +845,7 @@ class FilesWidget(QtWidgets.QFrame):
if not self._in_set_value:
self.value_changed.emit()
+ self._update_visibility()
def _on_split_request(self):
if self._multivalue:
@@ -836,29 +889,6 @@ class FilesWidget(QtWidgets.QFrame):
menu.popup(pos)
- def sizeHint(self):
- # Get size hints of widget and visible widgets
- result = super(FilesWidget, self).sizeHint()
- if not self._files_view.isVisible():
- not_visible_hint = self._files_view.sizeHint()
- else:
- not_visible_hint = self._empty_widget.sizeHint()
-
- # Get margins of this widget
- margins = self.layout().contentsMargins()
-
- # Change size hint based on result of maximum size hint of widgets
- result.setWidth(max(
- result.width(),
- not_visible_hint.width() + margins.left() + margins.right()
- ))
- result.setHeight(max(
- result.height(),
- not_visible_hint.height() + margins.top() + margins.bottom()
- ))
-
- return result
-
def dragEnterEvent(self, event):
if self._multivalue:
return
@@ -890,7 +920,6 @@ class FilesWidget(QtWidgets.QFrame):
mime_data = event.mimeData()
if mime_data.hasUrls():
event.accept()
- # event.setDropAction(QtCore.Qt.CopyAction)
filepaths = []
for url in mime_data.urls():
filepath = url.toLocalFile()
@@ -956,13 +985,15 @@ class FilesWidget(QtWidgets.QFrame):
def _add_filepaths(self, filepaths):
self._files_model.add_filepaths(filepaths)
- self._update_visibility()
def _remove_item_by_ids(self, item_ids):
self._files_model.remove_item_by_ids(item_ids)
- self._update_visibility()
def _update_visibility(self):
files_exists = self._files_proxy_model.rowCount() > 0
- self._files_view.setVisible(files_exists)
- self._empty_widget.setVisible(not files_exists)
+ if files_exists:
+ current_widget = self._files_view
+ else:
+ current_widget = self._empty_widget
+ self._layout.setCurrentWidget(current_widget)
+ self._files_view.update_remove_btn_visibility()
diff --git a/tests/lib/testing_classes.py b/tests/lib/testing_classes.py
index 85121f0d73..78a9f81095 100644
--- a/tests/lib/testing_classes.py
+++ b/tests/lib/testing_classes.py
@@ -10,7 +10,7 @@ import glob
import platform
from tests.lib.db_handler import DBHandler
-from distribution.file_handler import RemoteFileHandler
+from common.openpype_common.distribution.file_handler import RemoteFileHandler
class BaseTest: