From b1ebef457c23a3e48e077cd63040e7b15b9828a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Wed, 14 Sep 2022 11:36:10 +0200 Subject: [PATCH 01/30] :sparkles: add script for python dependencies info --- tools/get_python_packages_info.py | 83 +++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tools/get_python_packages_info.py diff --git a/tools/get_python_packages_info.py b/tools/get_python_packages_info.py new file mode 100644 index 0000000000..b4952840e6 --- /dev/null +++ b/tools/get_python_packages_info.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +"""Get version and license information on used Python packages. + +This is getting over all packages installed with Poetry and printing out +their name, version and available license information from PyPi in Markdown +table format. + +Usage: + ./.poetry/bin/poetry run python ./tools/get_python_packages_info.py + +""" + +import toml +import requests + + +packages = [] + +# define column headers +package_header = "Package" +version_header = "Version" +license_header = "License" + +name_col_width = len(package_header) +version_col_width = len(version_header) +license_col_width = len(license_header) + +# read lock file to get packages +with open("poetry.lock", "r") as fb: + lock_content = toml.load(fb) + + for package in lock_content["package"]: + # query pypi for license information + url = f"https://pypi.org/pypi/{package['name']}/json" + response = requests.get( + f"https://pypi.org/pypi/{package['name']}/json") + package_data = response.json() + version = package.get("version") or "N/A" + try: + package_license = package_data["info"].get("license") or "N/A" + except KeyError: + package_license = "N/A" + + if len(package_license) > 64: + package_license = f"{package_license[:32]}..." + packages.append( + ( + package["name"], + version, + package_license + ) + ) + + # update column width based on max string length + if len(package["name"]) > name_col_width: + name_col_width = len(package["name"]) + if len(version) > version_col_width: + version_col_width = len(version) + if len(package_license) > license_col_width: + license_col_width = len(package_license) + +# pad columns +name_col_width += 2 +version_col_width += 2 +license_col_width += 2 + +# print table header +print((f"|{package_header.center(name_col_width)}" + f"|{version_header.center(version_col_width)}" + f"|{license_header.center(license_col_width)}|")) + +print( + "|" + ("-" * len(package_header.center(name_col_width))) + + "|" + ("-" * len(version_header.center(version_col_width))) + + "|" + ("-" * len(license_header.center(license_col_width))) + "|") + +# print rest of the table +for package in packages: + print(( + f"|{package[0].center(name_col_width)}" + f"|{package[1].center(version_col_width)}" + f"|{package[2].center(license_col_width)}|" + )) From 3703ec07bcc709fb69cc57b19a66dc449c88f425 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 14 Sep 2022 18:23:17 +0200 Subject: [PATCH 02/30] OP-3940 - introduced new Settings for CollectVersion for Photoshop --- .../defaults/project_settings/photoshop.json | 3 +++ .../schema_project_photoshop.json | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/openpype/settings/defaults/project_settings/photoshop.json b/openpype/settings/defaults/project_settings/photoshop.json index 552c2c9cad..8ea36a3000 100644 --- a/openpype/settings/defaults/project_settings/photoshop.json +++ b/openpype/settings/defaults/project_settings/photoshop.json @@ -15,6 +15,9 @@ "CollectInstances": { "flatten_subset_template": "" }, + "CollectVersion": { + "sync_workfile_version": true + }, "ValidateContainers": { "enabled": true, "optional": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json index 7aa49c99a4..500c5d027b 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json @@ -131,6 +131,23 @@ } ] }, + { + "type": "dict", + "collapsible": true, + "key": "CollectVersion", + "label": "Collect Version", + "children": [ + { + "type": "label", + "label": "Synchronize version for image and review instances by workfile version." + }, + { + "type": "boolean", + "key": "sync_workfile_version", + "label": "Synchronize version with workfile" + } + ] + }, { "type": "schema_template", "name": "template_publish_plugin", From d93a18fd89bf749de62413b9280a21dde871c319 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 14 Sep 2022 18:25:11 +0200 Subject: [PATCH 03/30] OP-3940 - added new collector for Photoshop Single point of control if image and review instances should have their version synchronized according to workfile version. --- .../hosts/photoshop/plugins/CollectVersion.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 openpype/hosts/photoshop/plugins/CollectVersion.py diff --git a/openpype/hosts/photoshop/plugins/CollectVersion.py b/openpype/hosts/photoshop/plugins/CollectVersion.py new file mode 100644 index 0000000000..46f48b20fb --- /dev/null +++ b/openpype/hosts/photoshop/plugins/CollectVersion.py @@ -0,0 +1,28 @@ +import pyblish.api + + +class CollectVersion(pyblish.api.InstancePlugin): + """Collect version for publishable instances. + + Used to synchronize version from workfile to all publishable instances: + - image (manually created or color coded) + - review + + Dev comment: + Explicit collector created to control this from single place and not from + 3 different. + """ + order = pyblish.api.CollectorOrder + 0.200 + label = 'Collect Version' + + hosts = ["photoshop"] + families = ["image", "review"] + + # controlled by Settings + sync_workfile_version = False + + def process(self, instance): + if self.sync_workfile_version: + workfile_version = instance.context.data["version"] + self.log.debug(f"Applying version {workfile_version}") + instance.data["version"] = workfile_version From d0b8437cfd86113c6ffa3a04a0959bc80f3ddfcc Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 14 Sep 2022 18:32:08 +0200 Subject: [PATCH 04/30] OP-3940 - added optionality to collector There might be a reason when artist would like to skip this synchronization for specific workfile. --- openpype/hosts/photoshop/plugins/CollectVersion.py | 1 + openpype/settings/defaults/project_settings/photoshop.json | 1 + .../schemas/projects_schema/schema_project_photoshop.json | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/openpype/hosts/photoshop/plugins/CollectVersion.py b/openpype/hosts/photoshop/plugins/CollectVersion.py index 46f48b20fb..bc7af580d7 100644 --- a/openpype/hosts/photoshop/plugins/CollectVersion.py +++ b/openpype/hosts/photoshop/plugins/CollectVersion.py @@ -19,6 +19,7 @@ class CollectVersion(pyblish.api.InstancePlugin): families = ["image", "review"] # controlled by Settings + optional = True sync_workfile_version = False def process(self, instance): diff --git a/openpype/settings/defaults/project_settings/photoshop.json b/openpype/settings/defaults/project_settings/photoshop.json index 8ea36a3000..43a460052a 100644 --- a/openpype/settings/defaults/project_settings/photoshop.json +++ b/openpype/settings/defaults/project_settings/photoshop.json @@ -16,6 +16,7 @@ "flatten_subset_template": "" }, "CollectVersion": { + "optional": true, "sync_workfile_version": true }, "ValidateContainers": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json index 500c5d027b..e8dad84859 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json @@ -137,6 +137,11 @@ "key": "CollectVersion", "label": "Collect Version", "children": [ + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, { "type": "label", "label": "Synchronize version for image and review instances by workfile version." From 9ab7647d55b89919043efee3e36852607a1348b9 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 15 Sep 2022 10:57:19 +0200 Subject: [PATCH 05/30] OP-3940 - fixed location and name --- .../plugins/{CollectVersion.py => publish/collect_version.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openpype/hosts/photoshop/plugins/{CollectVersion.py => publish/collect_version.py} (100%) diff --git a/openpype/hosts/photoshop/plugins/CollectVersion.py b/openpype/hosts/photoshop/plugins/publish/collect_version.py similarity index 100% rename from openpype/hosts/photoshop/plugins/CollectVersion.py rename to openpype/hosts/photoshop/plugins/publish/collect_version.py From d905740208168114b12ec1a4873601d61c9b1798 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 15 Sep 2022 12:18:07 +0200 Subject: [PATCH 06/30] OP-3940 - collector cannot be optional --- openpype/settings/defaults/project_settings/photoshop.json | 1 - .../schemas/projects_schema/schema_project_photoshop.json | 5 ----- 2 files changed, 6 deletions(-) diff --git a/openpype/settings/defaults/project_settings/photoshop.json b/openpype/settings/defaults/project_settings/photoshop.json index 43a460052a..8ea36a3000 100644 --- a/openpype/settings/defaults/project_settings/photoshop.json +++ b/openpype/settings/defaults/project_settings/photoshop.json @@ -16,7 +16,6 @@ "flatten_subset_template": "" }, "CollectVersion": { - "optional": true, "sync_workfile_version": true }, "ValidateContainers": { diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json index e8dad84859..500c5d027b 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json @@ -137,11 +137,6 @@ "key": "CollectVersion", "label": "Collect Version", "children": [ - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, { "type": "label", "label": "Synchronize version for image and review instances by workfile version." From 18e03a8d28bc9e9fb0404c5f92475861e90f4f17 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 15 Sep 2022 12:46:31 +0200 Subject: [PATCH 07/30] OP-3940 - collector cannot be optional --- openpype/hosts/photoshop/plugins/publish/collect_version.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_version.py b/openpype/hosts/photoshop/plugins/publish/collect_version.py index bc7af580d7..46f48b20fb 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_version.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_version.py @@ -19,7 +19,6 @@ class CollectVersion(pyblish.api.InstancePlugin): families = ["image", "review"] # controlled by Settings - optional = True sync_workfile_version = False def process(self, instance): From b405299e92fe718993591892c71d59f76a604b5d Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 15 Sep 2022 15:33:57 +0200 Subject: [PATCH 08/30] OP-3940 - added collector for remote publishes In Webpublisher uploaded workfile name is not relieable, use last published + 1 instead. --- .../publish/collect_published_version.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 openpype/hosts/photoshop/plugins/publish/collect_published_version.py diff --git a/openpype/hosts/photoshop/plugins/publish/collect_published_version.py b/openpype/hosts/photoshop/plugins/publish/collect_published_version.py new file mode 100644 index 0000000000..2502689e4b --- /dev/null +++ b/openpype/hosts/photoshop/plugins/publish/collect_published_version.py @@ -0,0 +1,55 @@ +"""Collects published version of workfile and increments it. + +For synchronization of published image and workfile version it is required +to store workfile version from workfile file name in context.data["version"]. +In remote publishing this name is unreliable (artist might not follow naming +convention etc.), last published workfile version for particular workfile +subset is used instead. + +This plugin runs only in remote publishing (eg. Webpublisher). + +Requires: + context.data["assetEntity"] + +Provides: + context["version"] - incremented latest published workfile version +""" + +import pyblish.api + +from openpype.client import get_last_version_by_subset_name + + +class CollectPublishedVersion(pyblish.api.ContextPlugin): + """Collects published version of workfile and increments it.""" + + order = pyblish.api.CollectorOrder + 0.190 + label = "Collect published version" + hosts = ["photoshop"] + targets = ["remotepublish"] + + def process(self, context): + workfile_subset_name = None + for instance in context: + if instance.data["family"] == "workfile": + workfile_subset_name = instance.data["subset"] + break + + if not workfile_subset_name: + self.log.warning("No workfile instance found, " + "synchronization of version will not work.") + return + + project_name = context.data["projectName"] + asset_doc = context.data["assetEntity"] + asset_id = asset_doc["_id"] + + version_doc = get_last_version_by_subset_name(project_name, + workfile_subset_name, + asset_id) + version_int = 1 + if version_doc: + version_int += int(version_doc["name"]) + + self.log.debug(f"Setting {version_int} to context.") + context.data["version"] = version_int From abee82f45e48205c2e995dda9f53d8e92370cfed Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 15 Sep 2022 15:35:09 +0200 Subject: [PATCH 09/30] OP-3940 - fix wrong import for pype_commands --- openpype/pype_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index 85561495fd..f65d969c53 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -187,7 +187,7 @@ class PypeCommands: (to choose validator for example) """ - from openpype.hosts.webpublisher.cli_functions import ( + from openpype.hosts.webpublisher.publish_functions import ( cli_publish_from_app ) From bb6c8817608c7e6e0c5a5bc40b1652361efb1651 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 16 Sep 2022 11:15:25 +0200 Subject: [PATCH 10/30] OP-3940 - renamed sync_workfile_version to enabled --- .../hosts/photoshop/plugins/publish/collect_version.py | 10 +++------- .../settings/defaults/project_settings/photoshop.json | 2 +- .../projects_schema/schema_project_photoshop.json | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_version.py b/openpype/hosts/photoshop/plugins/publish/collect_version.py index 46f48b20fb..aff9f13bfb 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_version.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_version.py @@ -18,11 +18,7 @@ class CollectVersion(pyblish.api.InstancePlugin): hosts = ["photoshop"] families = ["image", "review"] - # controlled by Settings - sync_workfile_version = False - def process(self, instance): - if self.sync_workfile_version: - workfile_version = instance.context.data["version"] - self.log.debug(f"Applying version {workfile_version}") - instance.data["version"] = workfile_version + workfile_version = instance.context.data["version"] + self.log.debug(f"Applying version {workfile_version}") + instance.data["version"] = workfile_version diff --git a/openpype/settings/defaults/project_settings/photoshop.json b/openpype/settings/defaults/project_settings/photoshop.json index 8ea36a3000..9d74df7cd5 100644 --- a/openpype/settings/defaults/project_settings/photoshop.json +++ b/openpype/settings/defaults/project_settings/photoshop.json @@ -16,7 +16,7 @@ "flatten_subset_template": "" }, "CollectVersion": { - "sync_workfile_version": true + "enabled": false }, "ValidateContainers": { "enabled": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json index 500c5d027b..e63e25d2c2 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json @@ -143,8 +143,8 @@ }, { "type": "boolean", - "key": "sync_workfile_version", - "label": "Synchronize version with workfile" + "key": "enabled", + "label": "Enabled" } ] }, From 52e1b563672d757a19b7ab0452f291189f10de6f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 16 Sep 2022 11:47:05 +0200 Subject: [PATCH 11/30] OP-3952 - added text filter on project name to Tray Publisher --- openpype/tools/traypublisher/window.py | 13 +++++++++++++ openpype/tools/utils/models.py | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index cc33287091..d161afd37b 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -7,6 +7,7 @@ publishing plugins. """ from Qt import QtWidgets, QtCore +import qtawesome from openpype.pipeline import ( install_host, @@ -43,6 +44,7 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): projects_model = ProjectModel(dbcon) projects_proxy = ProjectSortFilterProxy() projects_proxy.setSourceModel(projects_model) + projects_proxy.setFilterKeyColumn(0) projects_view = QtWidgets.QListView(content_widget) projects_view.setObjectName("ChooseProjectView") @@ -59,10 +61,17 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): btns_layout.addWidget(cancel_btn, 0) btns_layout.addWidget(confirm_btn, 0) + txt_filter = QtWidgets.QLineEdit() + txt_filter.setPlaceholderText("Quick filter projects..") + txt_filter.setClearButtonEnabled(True) + txt_filter.addAction(qtawesome.icon("fa.filter", color="gray"), + QtWidgets.QLineEdit.LeadingPosition) + content_layout = QtWidgets.QVBoxLayout(content_widget) content_layout.setContentsMargins(0, 0, 0, 0) content_layout.setSpacing(20) content_layout.addWidget(header_label, 0) + content_layout.addWidget(txt_filter, 0) content_layout.addWidget(projects_view, 1) content_layout.addLayout(btns_layout, 0) @@ -79,11 +88,15 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): projects_view.doubleClicked.connect(self._on_double_click) confirm_btn.clicked.connect(self._on_confirm_click) cancel_btn.clicked.connect(self._on_cancel_click) + txt_filter.textChanged.connect( + lambda: projects_proxy.setFilterRegularExpression( + txt_filter.text())) self._projects_view = projects_view self._projects_model = projects_model self._cancel_btn = cancel_btn self._confirm_btn = confirm_btn + self._txt_filter = txt_filter self._publisher_window = publisher_window self._project_name = None diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 1faccef4dd..817d9c0944 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -356,10 +356,12 @@ class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel): def filterAcceptsRow(self, source_row, source_parent): index = self.sourceModel().index(source_row, 0, source_parent) + string_pattern = self.filterRegularExpression().pattern() if self._filter_enabled: result = self._custom_index_filter(index) if result is not None: - return result + project_name = index.data(PROJECT_NAME_ROLE) + return string_pattern in project_name return super(ProjectSortFilterProxy, self).filterAcceptsRow( source_row, source_parent From ef33cda784b591e1faa899b9c4db9994146222fe Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 16 Sep 2022 12:46:06 +0200 Subject: [PATCH 12/30] OP-3952 - used PlaceholderLineEdit Changed lambda to separate method as lamba is supposed to have some issue during QtDestroy --- openpype/tools/traypublisher/window.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index d161afd37b..6c17c66016 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -20,6 +20,7 @@ from openpype.tools.utils.models import ( ProjectModel, ProjectSortFilterProxy ) +from openpype.tools.utils import PlaceholderLineEdit class StandaloneOverlayWidget(QtWidgets.QFrame): @@ -61,7 +62,7 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): btns_layout.addWidget(cancel_btn, 0) btns_layout.addWidget(confirm_btn, 0) - txt_filter = QtWidgets.QLineEdit() + txt_filter = PlaceholderLineEdit(content_widget) txt_filter.setPlaceholderText("Quick filter projects..") txt_filter.setClearButtonEnabled(True) txt_filter.addAction(qtawesome.icon("fa.filter", color="gray"), @@ -88,12 +89,11 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): projects_view.doubleClicked.connect(self._on_double_click) confirm_btn.clicked.connect(self._on_confirm_click) cancel_btn.clicked.connect(self._on_cancel_click) - txt_filter.textChanged.connect( - lambda: projects_proxy.setFilterRegularExpression( - txt_filter.text())) + txt_filter.textChanged.connect(self._on_text_changed) self._projects_view = projects_view self._projects_model = projects_model + self._projects_proxy = projects_proxy self._cancel_btn = cancel_btn self._confirm_btn = confirm_btn self._txt_filter = txt_filter @@ -115,6 +115,10 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): def _on_cancel_click(self): self._set_project(self._project_name) + def _on_text_changed(self): + self._projects_proxy.setFilterRegularExpression( + self._txt_filter.text()) + def set_selected_project(self): index = self._projects_view.currentIndex() From 210a3e05525913f7439b805c9671e38b7bae40db Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 16 Sep 2022 14:19:07 +0200 Subject: [PATCH 13/30] OP-3953 - added persisting of last selected project in Tray Publisher Last selected project is stored in .json in app folder - eg. next to unzipped version zip. --- openpype/tools/traypublisher/window.py | 32 ++++++++++++++++++++++++++ openpype/tools/utils/models.py | 13 +++++++++++ 2 files changed, 45 insertions(+) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index cc33287091..2d32b5d6bf 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -19,6 +19,25 @@ from openpype.tools.utils.models import ( ProjectModel, ProjectSortFilterProxy ) +import appdirs +from openpype.lib import JSONSettingRegistry + + +class TrayPublisherRegistry(JSONSettingRegistry): + """Class handling OpenPype general settings registry. + + Attributes: + vendor (str): Name used for path construction. + product (str): Additional name used for path construction. + + """ + + def __init__(self): + self.vendor = "pypeclub" + self.product = "openpype" + name = "tray_publisher" + path = appdirs.user_data_dir(self.product, self.vendor) + super(TrayPublisherRegistry, self).__init__(name, path) class StandaloneOverlayWidget(QtWidgets.QFrame): @@ -90,6 +109,16 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): def showEvent(self, event): self._projects_model.refresh() + + setting_registry = TrayPublisherRegistry() + project_name = setting_registry.get_item("project_name") + if project_name: + index = self._projects_model.get_index(project_name) + if index: + mode = QtCore.QItemSelectionModel.Select | \ + QtCore.QItemSelectionModel.Rows + self._projects_view.selectionModel().select(index, mode) + self._cancel_btn.setVisible(self._project_name is not None) super(StandaloneOverlayWidget, self).showEvent(event) @@ -119,6 +148,9 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): self.setVisible(False) self.project_selected.emit(project_name) + setting_registry = TrayPublisherRegistry() + setting_registry.set_item("project_name", project_name) + class TrayPublishWindow(PublisherWindow): def __init__(self, *args, **kwargs): diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 1faccef4dd..2d917fcc49 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -330,6 +330,19 @@ class ProjectModel(QtGui.QStandardItemModel): if new_items: root_item.appendRows(new_items) + def get_index(self, project_name): + """ + Get index of 'project_name' value. + + Args: + project_name (str): + Returns: + (QModelIndex) + """ + val = self._items_by_name.get(project_name) + if val: + return self.indexFromItem(val) + class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel): def __init__(self, *args, **kwargs): From 7331fd20691ba2a7047d98e7baa0e7c04ce750e6 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 16 Sep 2022 14:28:04 +0200 Subject: [PATCH 14/30] formatting change Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/tools/traypublisher/window.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index 2d32b5d6bf..56c5594638 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -115,8 +115,9 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): if project_name: index = self._projects_model.get_index(project_name) if index: - mode = QtCore.QItemSelectionModel.Select | \ - QtCore.QItemSelectionModel.Rows + mode = ( + QtCore.QItemSelectionModel.Select + | QtCore.QItemSelectionModel.Rows) self._projects_view.selectionModel().select(index, mode) self._cancel_btn.setVisible(self._project_name is not None) From ad4211656b7651b7eef42351aa13240add36a109 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 17 Sep 2022 10:52:36 +0200 Subject: [PATCH 15/30] Remove double setting of additional attributes for Arnold --- openpype/hosts/maya/api/lib_rendersettings.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index 7cd2193086..67b66b8024 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -133,20 +133,7 @@ class RenderSettings(object): cmds.setAttr( "defaultArnoldDriver.mergeAOVs", multi_exr) - # Passes additional options in from the schema as a list - # but converts it to a dictionary because ftrack doesn't - # allow fullstops in custom attributes. Then checks for - # type of MtoA attribute passed to adjust the `setAttr` - # command accordingly. self._additional_attribs_setter(additional_options) - for item in additional_options: - attribute, value = item - if (cmds.getAttr(str(attribute), type=True)) == "long": - cmds.setAttr(str(attribute), int(value)) - elif (cmds.getAttr(str(attribute), type=True)) == "bool": - cmds.setAttr(str(attribute), int(value), type = "Boolean") # noqa - elif (cmds.getAttr(str(attribute), type=True)) == "string": - cmds.setAttr(str(attribute), str(value), type = "string") # noqa reset_frame_range() def _set_redshift_settings(self, width, height): From 2c8eaec2d7c93e53accfec87d828bf8648d38428 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 17 Sep 2022 11:04:12 +0200 Subject: [PATCH 16/30] Remove debug print statement --- openpype/hosts/maya/api/lib_rendersettings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index 67b66b8024..a62145e921 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -217,7 +217,6 @@ class RenderSettings(object): cmds.setAttr("defaultRenderGlobals.extensionPadding", 4) def _additional_attribs_setter(self, additional_attribs): - print(additional_attribs) for item in additional_attribs: attribute, value = item if (cmds.getAttr(str(attribute), type=True)) == "long": From 0c71ec1d3840db418a4077efa1eddc57436f4d27 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 17 Sep 2022 13:18:04 +0200 Subject: [PATCH 17/30] Tweak readability, log error on unsupported attribute type --- openpype/hosts/maya/api/lib_rendersettings.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index a62145e921..0618420b2b 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -5,6 +5,7 @@ import maya.mel as mel import six import sys +from openpype.lib import Logger from openpype.api import ( get_project_settings, get_current_project_settings @@ -38,6 +39,8 @@ class RenderSettings(object): "underscore": "_" } + log = Logger.get_logger("RenderSettings") + @classmethod def get_image_prefix_attr(cls, renderer): return cls._image_prefix_nodes[renderer] @@ -219,9 +222,16 @@ class RenderSettings(object): def _additional_attribs_setter(self, additional_attribs): for item in additional_attribs: attribute, value = item - if (cmds.getAttr(str(attribute), type=True)) == "long": - cmds.setAttr(str(attribute), int(value)) - elif (cmds.getAttr(str(attribute), type=True)) == "bool": - cmds.setAttr(str(attribute), int(value)) # noqa - elif (cmds.getAttr(str(attribute), type=True)) == "string": - cmds.setAttr(str(attribute), str(value), type = "string") # noqa + attribute = str(attribute) # ensure str conversion from settings + attribute_type = cmds.getAttr(attribute, type=True) + if attribute_type in {"long", "bool"}: + cmds.setAttr(attribute, int(value)) + elif attribute_type == "string": + cmds.setAttr(attribute, str(value), type="string") + else: + self.log.error( + "Attribute {attribute} can not be set due to unsupported " + "type: {attribute_type}".format( + attribute=attribute, + attribute_type=attribute_type) + ) From 83922a87cd08630b549cb6f0220aaacfcb5623ec Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 17 Sep 2022 13:19:37 +0200 Subject: [PATCH 18/30] Add double attribute support (float) --- openpype/hosts/maya/api/lib_rendersettings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py index 0618420b2b..777a6ffbc9 100644 --- a/openpype/hosts/maya/api/lib_rendersettings.py +++ b/openpype/hosts/maya/api/lib_rendersettings.py @@ -228,6 +228,8 @@ class RenderSettings(object): cmds.setAttr(attribute, int(value)) elif attribute_type == "string": cmds.setAttr(attribute, str(value), type="string") + elif attribute_type in {"double", "doubleAngle", "doubleLinear"}: + cmds.setAttr(attribute, float(value)) else: self.log.error( "Attribute {attribute} can not be set due to unsupported " From b36e1ded7d24c74b0601d0c65567f4674d6bf212 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 17 Sep 2022 13:29:38 +0200 Subject: [PATCH 19/30] Set default image format for V-Ray+Redshift to exr instead of png and iff --- openpype/settings/defaults/project_settings/maya.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 8643297f02..76ef0a7338 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -49,7 +49,7 @@ "vray_renderer": { "image_prefix": "maya///", "engine": "1", - "image_format": "png", + "image_format": "exr", "aov_list": [], "additional_options": [] }, @@ -57,7 +57,7 @@ "image_prefix": "maya///", "primary_gi_engine": "0", "secondary_gi_engine": "0", - "image_format": "iff", + "image_format": "exr", "multilayer_exr": true, "force_combine": true, "aov_list": [], From b48ad01e4c6ada98a96f048d93615fa072190b86 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 10:48:44 +0200 Subject: [PATCH 20/30] Changed function name Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/tools/utils/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 2d917fcc49..d072ff297d 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -330,7 +330,7 @@ class ProjectModel(QtGui.QStandardItemModel): if new_items: root_item.appendRows(new_items) - def get_index(self, project_name): + def find_project(self, project_name): """ Get index of 'project_name' value. From ae7f7ebabbd69352fab23f7bc9757c90c80881b5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 10:54:23 +0200 Subject: [PATCH 21/30] OP-3953 - added missing mapping to proxy model --- openpype/tools/traypublisher/window.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index 56c5594638..0c99a55998 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -113,7 +113,10 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): setting_registry = TrayPublisherRegistry() project_name = setting_registry.get_item("project_name") if project_name: - index = self._projects_model.get_index(project_name) + index = None + src_index = self._projects_model.find_project(project_name) + if src_index is not None: + index = self._projects_proxy.mapFromSource(src_index) if index: mode = ( QtCore.QItemSelectionModel.Select From 94aa11f1167e90719ef9426bfae78492b7491366 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 10:57:47 +0200 Subject: [PATCH 22/30] OP-3953 - added missing proxy model variable --- openpype/tools/traypublisher/window.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index 0c99a55998..ca8c0758d6 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -101,6 +101,7 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): self._projects_view = projects_view self._projects_model = projects_model + self._projects_proxy = projects_proxy self._cancel_btn = cancel_btn self._confirm_btn = confirm_btn From f711b529b9693d73d08d696acba077bf45ba3f77 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 11:01:52 +0200 Subject: [PATCH 23/30] OP-3952 - safer resolving of search pattern --- openpype/tools/utils/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 817d9c0944..6663ca1b0a 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -361,7 +361,9 @@ class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel): result = self._custom_index_filter(index) if result is not None: project_name = index.data(PROJECT_NAME_ROLE) - return string_pattern in project_name + if project_name is None: + return result + return string_pattern.lower() in project_name.lower() return super(ProjectSortFilterProxy, self).filterAcceptsRow( source_row, source_parent From 31beb5b6b15a4c7b110c21ebafc71eb3163b004b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 11:03:15 +0200 Subject: [PATCH 24/30] OP-3952 - sort projects after refresh --- openpype/tools/traypublisher/window.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index 6c17c66016..b134e8ab86 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -103,6 +103,8 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): def showEvent(self, event): self._projects_model.refresh() + # Sort projects after refresh + self._projects_proxy.sort(0) self._cancel_btn.setVisible(self._project_name is not None) super(StandaloneOverlayWidget, self).showEvent(event) From a5b2d8c6bd8a6c6ee6ed636deb3d823d9103aabb Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 11:04:47 +0200 Subject: [PATCH 25/30] OP-3952 - set sorting as case insensitive --- openpype/tools/utils/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index 6663ca1b0a..f31a56b2f4 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -335,6 +335,9 @@ class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel): def __init__(self, *args, **kwargs): super(ProjectSortFilterProxy, self).__init__(*args, **kwargs) self._filter_enabled = True + # Disable case sensitivity + self.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive) + self._filter_enabled = True def lessThan(self, left_index, right_index): if left_index.data(PROJECT_NAME_ROLE) is None: From 222c64b0c68f6dbde3ac8b6bdf33db51732449e4 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 11:45:58 +0200 Subject: [PATCH 26/30] OP-3953 - handle missing registry json file --- openpype/tools/traypublisher/window.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/tools/traypublisher/window.py b/openpype/tools/traypublisher/window.py index ca8c0758d6..f3ed01b151 100644 --- a/openpype/tools/traypublisher/window.py +++ b/openpype/tools/traypublisher/window.py @@ -112,7 +112,11 @@ class StandaloneOverlayWidget(QtWidgets.QFrame): self._projects_model.refresh() setting_registry = TrayPublisherRegistry() - project_name = setting_registry.get_item("project_name") + try: + project_name = setting_registry.get_item("project_name") + except ValueError: + project_name = None + if project_name: index = None src_index = self._projects_model.find_project(project_name) From 091498e13017cc96d0638f34fb03b0f0caee59e8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 11:57:29 +0200 Subject: [PATCH 27/30] OP-3952 - remove duplicated field Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/tools/utils/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index f31a56b2f4..cff5238a69 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -337,7 +337,6 @@ class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel): self._filter_enabled = True # Disable case sensitivity self.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive) - self._filter_enabled = True def lessThan(self, left_index, right_index): if left_index.data(PROJECT_NAME_ROLE) is None: From 56dcb25dc056b892af0939236d18abda6967ee96 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 19 Sep 2022 18:23:08 +0200 Subject: [PATCH 28/30] Updated args to maketx Better logging. --- .../maya/plugins/publish/extract_look.py | 54 ++++++++----------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index 91b0da75c6..dd705324b9 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -13,7 +13,7 @@ from maya import cmds # noqa import pyblish.api -from openpype.lib import source_hash +from openpype.lib import source_hash, run_subprocess from openpype.pipeline import legacy_io, publish from openpype.hosts.maya.api import lib @@ -68,7 +68,7 @@ def find_paths_by_hash(texture_hash): return legacy_io.distinct(key, {"type": "version"}) -def maketx(source, destination, *args): +def maketx(source, destination, args, logger): """Make `.tx` using `maketx` with some default settings. The settings are based on default as used in Arnold's @@ -79,7 +79,8 @@ def maketx(source, destination, *args): Args: source (str): Path to source file. destination (str): Writing destination path. - *args: Additional arguments for `maketx`. + args: Additional arguments for `maketx`. + logger Returns: str: Output of `maketx` command. @@ -94,7 +95,7 @@ def maketx(source, destination, *args): "OIIO tool not found in {}".format(maketx_path)) raise AssertionError("OIIO tool not found") - cmd = [ + subprocess_args = [ maketx_path, "-v", # verbose "-u", # update mode @@ -103,27 +104,20 @@ def maketx(source, destination, *args): "--checknan", # use oiio-optimized settings for tile-size, planarconfig, metadata "--oiio", - "--filter lanczos3", - escape_space(source) + "--filter", "lanczos3", + source ] - cmd.extend(args) - cmd.extend(["-o", escape_space(destination)]) + subprocess_args.extend(args) + subprocess_args.extend(["-o", destination]) - cmd = " ".join(cmd) + cmd = " ".join(subprocess_args) + logger.debug(cmd) - CREATE_NO_WINDOW = 0x08000000 # noqa - kwargs = dict(args=cmd, stderr=subprocess.STDOUT) - - if sys.platform == "win32": - kwargs["creationflags"] = CREATE_NO_WINDOW try: - out = subprocess.check_output(**kwargs) - except subprocess.CalledProcessError as exc: - print(exc) - import traceback - - traceback.print_exc() + out = run_subprocess(subprocess_args) + except Exception: + logger.error("Maketx converion failed", exc_info=True) raise return out @@ -524,15 +518,17 @@ class ExtractLook(publish.Extractor): if do_maketx and ext != ".tx": # Produce .tx file in staging if source file is not .tx converted = os.path.join(staging, "resources", fname + ".tx") - + additional_args = [ + "--sattrib", + "sourceHash", + texture_hash + ] if linearize: self.log.info("tx: converting sRGB -> linear") - colorconvert = "--colorconvert sRGB linear" - else: - colorconvert = "" + additional_args.extend(["--colorconvert", "sRGB", "linear"]) config_path = get_ocio_config_path("nuke-default") - color_config = "--colorconfig {0}".format(config_path) + additional_args.extend(["--colorconfig", config_path]) # Ensure folder exists if not os.path.exists(os.path.dirname(converted)): os.makedirs(os.path.dirname(converted)) @@ -541,12 +537,8 @@ class ExtractLook(publish.Extractor): maketx( filepath, converted, - # Include `source-hash` as string metadata - "--sattrib", - "sourceHash", - escape_space(texture_hash), - colorconvert, - color_config + additional_args, + self.log ) return converted, COPY, texture_hash From c43b952357c9c69798adcd3fb04fc2d6dbc85100 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 20 Sep 2022 11:15:39 +0200 Subject: [PATCH 29/30] Updated docstring Co-authored-by: Roy Nieterau --- openpype/hosts/maya/plugins/publish/extract_look.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index dd705324b9..403b4ee6bc 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -79,8 +79,8 @@ def maketx(source, destination, args, logger): Args: source (str): Path to source file. destination (str): Writing destination path. - args: Additional arguments for `maketx`. - logger + args (list): Additional arguments for `maketx`. + logger (logging.Logger): Logger to log messages to. Returns: str: Output of `maketx` command. From 7e65bdd096b7ee3c9ae927374d2c5c89270cd9b3 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 20 Sep 2022 16:39:00 +0200 Subject: [PATCH 30/30] OP-3923 - fix issue in Hero hardlinks Disk must be NTFS format or it will throw "WinError 1", which matches to EINVAL. Still raise different errors. --- openpype/plugins/publish/integrate_hero_version.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 96d768e1c1..c0760a5471 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -577,8 +577,11 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin): return except OSError as exc: - # re-raise exception if different than cross drive path - if exc.errno != errno.EXDEV: + # re-raise exception if different than + # EXDEV - cross drive path + # EINVAL - wrong format, must be NTFS + self.log.debug("Hardlink failed with errno:'{}'".format(exc.errno)) + if exc.errno not in [errno.EXDEV, errno.EINVAL]: raise shutil.copy(src_path, dst_path)