From 7f4f32f450807978567360fab2faf59d19c945df Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 12:21:16 +0100 Subject: [PATCH 01/15] add 'create_at' information to report item data --- openpype/tools/publisher/control.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index b02d83e4f6..125d93b6fd 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -4,6 +4,7 @@ import logging import traceback import collections import uuid +import datetime import tempfile import shutil import inspect @@ -285,6 +286,8 @@ class PublishReportMaker: def get_report(self, publish_plugins=None): """Report data with all details of current state.""" + + now = datetime.datetime.now() instances_details = {} for instance in self._all_instances_by_id.values(): instances_details[instance.id] = self._extract_instance_data( @@ -334,7 +337,8 @@ class PublishReportMaker: "context": self._extract_context_data(self._current_context), "crashed_file_paths": crashed_file_paths, "id": uuid.uuid4().hex, - "report_version": "1.0.0" + "created_at": now.strftime("%Y-%m-%d %H:%M:%S"), + "report_version": "1.0.1", } def _extract_context_data(self, context): From 1e78259d3a3c7f7a8ca50fb470957772d6d9fdd8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 12:23:44 +0100 Subject: [PATCH 02/15] added 'created_at' with auto fix for older report items --- .../publisher/publish_report_viewer/window.py | 149 +++++++++++++++--- 1 file changed, 129 insertions(+), 20 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index dc4ad70934..533b9de15f 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -2,6 +2,7 @@ import os import json import six import uuid +import datetime import appdirs from qtpy import QtWidgets, QtCore, QtGui @@ -47,47 +48,79 @@ class PublishReportItem: """Report item representing one file in report directory.""" def __init__(self, content): - item_id = content.get("id") - changed = False - if not item_id: - item_id = str(uuid.uuid4()) - changed = True - content["id"] = item_id + changed = self._fix_content(content) - if not content.get("report_version"): - changed = True - content["report_version"] = "0.0.1" - - report_path = os.path.join(get_reports_dir(), item_id) + report_path = os.path.join(get_reports_dir(), content["id"]) file_modified = None if os.path.exists(report_path): file_modified = os.path.getmtime(report_path) + + created_at_obj = datetime.datetime.strptime( + content["created_at"], "%Y-%m-%d %H:%M:%S" + ) + created_at = self.date_obj_to_timestamp(created_at_obj) + self.content = content self.report_path = report_path self.file_modified = file_modified + self.created_at = float(created_at) self._loaded_label = content.get("label") self._changed = changed self.publish_report = PublishReport(content) @property def version(self): + """Publish report version. + + Returns: + str: Publish report version. + """ return self.content["report_version"] @property def id(self): + """Publish report id. + + Returns: + str: Publish report id. + """ + return self.content["id"] def get_label(self): + """Publish report label. + + Returns: + str: Publish report label showed in UI. + """ + return self.content.get("label") or "Unfilled label" def set_label(self, label): + """Set publish report label. + + Args: + label (str): New publish report label. + """ + if not label: self.content.pop("label", None) self.content["label"] = label label = property(get_label, set_label) + @property + def loaded_label(self): + return self._loaded_label + + def mark_as_changed(self): + """Mark report as changed.""" + + self._changed = True + def save(self): + """Save publish report to file.""" + save = False if ( self._changed @@ -109,6 +142,15 @@ class PublishReportItem: @classmethod def from_filepath(cls, filepath): + """Create report item from file. + + Args: + filepath (str): Path to report file. Content must be json. + + Returns: + PublishReportItem: Report item. + """ + if not os.path.exists(filepath): return None @@ -116,15 +158,25 @@ class PublishReportItem: with open(filepath, "r") as stream: content = json.load(stream) - return cls(content) + file_modified = os.path.getmtime(filepath) + changed = cls._fix_content(content, file_modified=file_modified) + obj = cls(content) + if changed: + obj.mark_as_changed() + return obj + except Exception: return None def remove_file(self): + """Remove report file.""" + if os.path.exists(self.report_path): os.remove(self.report_path) def update_file_content(self): + """Update report content in file.""" + if not os.path.exists(self.report_path): return @@ -148,6 +200,63 @@ class PublishReportItem: self.content = content self.file_modified = file_modified + @staticmethod + def date_obj_to_timestamp(date_obj): + if hasattr(date_obj, "timestamp"): + return date_obj.timestamp() + + # Python 2 support + epoch = datetime.datetime.fromtimestamp(0) + return (date_obj - epoch).total_seconds() + + @classmethod + def _fix_content(cls, content, file_modified=None): + """Fix content for backward compatibility of older report items. + + Args: + content (dict[str, Any]): Report content. + file_modified (Optional[float]): File modification time. + + Returns: + bool: True if content was changed, False otherwise. + """ + + # Fix created_at key + changed = cls._fix_created_at(content, file_modified) + + # NOTE backward compatibility for 'id' and 'report_version' is from + # 28.10.2022 https://github.com/ynput/OpenPype/pull/4040 + # We can probably safely remove it + + # Fix missing 'id' + item_id = content.get("id") + if not item_id: + item_id = str(uuid.uuid4()) + changed = True + content["id"] = item_id + + # Fix missing 'report_version' + if not content.get("report_version"): + changed = True + content["report_version"] = "0.0.1" + return changed + + @classmethod + def _fix_created_at(cls, content, file_modified): + # Key 'create_at' was added in report version 1.0.1 + created_at = content.get("created_at") + if created_at: + return False + + # Auto fix 'created_at', use file modification time if it is not set + # , or current time if modification could not be received. + if file_modified is not None: + created_at_obj = datetime.datetime.fromtimestamp(file_modified) + else: + created_at_obj = datetime.datetime.now() + content["created_at"] = created_at_obj.strftime("%Y-%m-%d %H:%M:%S") + return True + class PublisherReportHandler: """Class handling storing publish report tool.""" @@ -278,16 +387,16 @@ class LoadedFilesModel(QtGui.QStandardItemModel): new_items = [] for normalized_path in filtered_paths: - try: - with open(normalized_path, "r") as stream: - data = json.load(stream) - report_item = PublishReportItem(data) - except Exception: - # TODO handle errors + report_item = PublishReportItem.from_filepath(normalized_path) + if report_item is None: continue - label = data.get("label") - if not label: + # Skip already added report items + # QUESTION: Should we replace existing or skip the item? + if report_item.id in self._items_by_id: + continue + + if not report_item.loaded_label: report_item.label = ( os.path.splitext(os.path.basename(filepath))[0] ) From 5f6d6ca1b3b55011735d468f7839c2076a4c0c8a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 12:24:55 +0100 Subject: [PATCH 03/15] use created at as sorting value --- .../publisher/publish_report_viewer/window.py | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 533b9de15f..0d7042a69c 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -26,6 +26,7 @@ else: ITEM_ID_ROLE = QtCore.Qt.UserRole + 1 +ITEM_CREATED_AT_ROLE = QtCore.Qt.UserRole + 2 def get_reports_dir(): @@ -300,9 +301,16 @@ class PublisherReportHandler: class LoadedFilesModel(QtGui.QStandardItemModel): + header_labels = ("Reports", "Created") + def __init__(self, *args, **kwargs): super(LoadedFilesModel, self).__init__(*args, **kwargs) + # Column count must be set before setting header data + self.setColumnCount(len(self.header_labels)) + for col, label in enumerate(self.header_labels): + self.setHeaderData(col, QtCore.Qt.Horizontal, label) + self._items_by_id = {} self._report_items_by_id = {} @@ -311,10 +319,15 @@ class LoadedFilesModel(QtGui.QStandardItemModel): self._loading_registry = False def refresh(self): - self._handler.reset() + root_item = self.invisibleRootItem() + if root_item.rowCount(): + root_item.removeRows(0, root_item.rowCount()) + self._items_by_id = {} self._report_items_by_id = {} + self._handler.reset() + new_items = [] for report_item in self._handler.list_reports(): item = self._create_item(report_item) @@ -326,26 +339,26 @@ class LoadedFilesModel(QtGui.QStandardItemModel): root_item = self.invisibleRootItem() root_item.appendRows(new_items) - def headerData(self, section, orientation, role): - if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole): - if section == 0: - return "Exports" - if section == 1: - return "Modified" - return "" - super(LoadedFilesModel, self).headerData(section, orientation, role) - def data(self, index, role=None): if role is None: role = QtCore.Qt.DisplayRole col = index.column() + if col == 1: + if role in ( + QtCore.Qt.DisplayRole, QtCore.Qt.InitialSortOrderRole + ): + role = ITEM_CREATED_AT_ROLE + if col != 0: index = self.index(index.row(), 0, index.parent()) return super(LoadedFilesModel, self).data(index, role) - def setData(self, index, value, role): + def setData(self, index, value, role=None): + if role is None: + role = QtCore.Qt.EditRole + if role == QtCore.Qt.EditRole: item_id = index.data(ITEM_ID_ROLE) report_item = self._report_items_by_id.get(item_id) @@ -356,6 +369,12 @@ class LoadedFilesModel(QtGui.QStandardItemModel): return super(LoadedFilesModel, self).setData(index, value, role) + def flags(self, index): + # Allow editable flag only for first column + if index.column() > 0: + return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled + return super(LoadedFilesModel, self).flags(index) + def _create_item(self, report_item): if report_item.id in self._items_by_id: return None @@ -363,6 +382,7 @@ class LoadedFilesModel(QtGui.QStandardItemModel): item = QtGui.QStandardItem(report_item.label) item.setColumnCount(self.columnCount()) item.setData(report_item.id, ITEM_ID_ROLE) + item.setData(report_item.created_at, ITEM_CREATED_AT_ROLE) return item @@ -444,13 +464,18 @@ class LoadedFilesView(QtWidgets.QTreeView): ) self.setIndentation(0) self.setAlternatingRowColors(True) + self.setSortingEnabled(True) model = LoadedFilesModel() - self.setModel(model) + proxy_model = QtCore.QSortFilterProxyModel() + proxy_model.setSourceModel(model) + self.setModel(proxy_model) time_delegate = PrettyTimeDelegate() self.setItemDelegateForColumn(1, time_delegate) + self.sortByColumn(1, QtCore.Qt.AscendingOrder) + remove_btn = IconButton(self) remove_icon_path = resources.get_icon_path("delete") loaded_remove_image = QtGui.QImage(remove_icon_path) @@ -465,6 +490,7 @@ class LoadedFilesView(QtWidgets.QTreeView): ) self._model = model + self._proxy_model = proxy_model self._time_delegate = time_delegate self._remove_btn = remove_btn From 8bb497e64b91936e71b5b2263e34e937ac875022 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 12:25:13 +0100 Subject: [PATCH 04/15] renamed 'remove_report_items' tp 'remove_report_item' --- .../tools/publisher/publish_report_viewer/window.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 0d7042a69c..1557f2bd0b 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -290,7 +290,15 @@ class PublisherReportHandler: self._reports_by_id = reports_by_id return reports - def remove_report_items(self, item_id): + def remove_report_item(self, item_id): + """Remove report item by id. + + Remove from cache and also remove the file with the content. + + Args: + item_id (str): Report item id. + """ + item = self._reports_by_id.get(item_id) if item: try: @@ -439,7 +447,7 @@ class LoadedFilesModel(QtGui.QStandardItemModel): if not report_item: return - self._handler.remove_report_items(item_id) + self._handler.remove_report_item(item_id) item = self._items_by_id.get(item_id) parent = self.invisibleRootItem() From 64ef575ccecee9af8715fbcdaf8aca1c10825fcc Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 12:25:29 +0100 Subject: [PATCH 05/15] modified docstring --- openpype/tools/publisher/publish_report_viewer/window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 1557f2bd0b..ffb2d64be6 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -260,7 +260,7 @@ class PublishReportItem: class PublisherReportHandler: - """Class handling storing publish report tool.""" + """Class handling storing publish report items.""" def __init__(self): self._reports = None From 46f05968bcabf82e05b8f9d693ce23629abbd066 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 12:25:44 +0100 Subject: [PATCH 06/15] add loaded report item only if could be created --- openpype/tools/publisher/publish_report_viewer/window.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index ffb2d64be6..84b25467b4 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -283,8 +283,9 @@ class PublisherReportHandler: continue filepath = os.path.join(report_dir, filename) item = PublishReportItem.from_filepath(filepath) - reports.append(item) - reports_by_id[item.id] = item + if item is not None: + reports.append(item) + reports_by_id[item.id] = item self._reports = reports self._reports_by_id = reports_by_id From 25a0e64a068f50d2f955b6e2a95c743d7d742abc Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 15:51:05 +0100 Subject: [PATCH 07/15] removed unnecessary 'date_obj_to_timestamp' --- .../tools/publisher/publish_report_viewer/window.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 84b25467b4..9dbe991201 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -59,7 +59,7 @@ class PublishReportItem: created_at_obj = datetime.datetime.strptime( content["created_at"], "%Y-%m-%d %H:%M:%S" ) - created_at = self.date_obj_to_timestamp(created_at_obj) + created_at = created_at_obj.timestamp() self.content = content self.report_path = report_path @@ -201,15 +201,6 @@ class PublishReportItem: self.content = content self.file_modified = file_modified - @staticmethod - def date_obj_to_timestamp(date_obj): - if hasattr(date_obj, "timestamp"): - return date_obj.timestamp() - - # Python 2 support - epoch = datetime.datetime.fromtimestamp(0) - return (date_obj - epoch).total_seconds() - @classmethod def _fix_content(cls, content, file_modified=None): """Fix content for backward compatibility of older report items. From 6db0dcbb44cc63c83113ef04af56e6e999cd5d41 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 27 Dec 2023 15:55:39 +0100 Subject: [PATCH 08/15] Fix weird comment --- openpype/tools/publisher/publish_report_viewer/window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 9dbe991201..7cc7c6366a 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -241,7 +241,7 @@ class PublishReportItem: return False # Auto fix 'created_at', use file modification time if it is not set - # , or current time if modification could not be received. + # or current time if modification could not be received. if file_modified is not None: created_at_obj = datetime.datetime.fromtimestamp(file_modified) else: From f7fba84aeec00977ef893f6696eeb7c2ab8e749d Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 16:33:22 +0100 Subject: [PATCH 09/15] fix '_fill_selection' by accessing model method --- openpype/tools/publisher/publish_report_viewer/window.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 7cc7c6366a..ea78571223 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -538,7 +538,8 @@ class LoadedFilesView(QtWidgets.QTreeView): if index.isValid(): return - index = self._model.index(0, 0) + model = self.model() + index = model.index(0, 0) if index.isValid(): self.setCurrentIndex(index) From 78460c2d38d4111e3b3dd0403b2148eaa3159e88 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 16:43:00 +0100 Subject: [PATCH 10/15] remove items from _report_items_by_id and _items_by_id --- .../tools/publisher/publish_report_viewer/window.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index ea78571223..283d6284d6 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -435,15 +435,13 @@ class LoadedFilesModel(QtGui.QStandardItemModel): root_item.appendRows(new_items) def remove_item_by_id(self, item_id): - report_item = self._report_items_by_id.get(item_id) - if not report_item: - return - self._handler.remove_report_item(item_id) - item = self._items_by_id.get(item_id) - parent = self.invisibleRootItem() - parent.removeRow(item.row()) + self._report_items_by_id.pop(item_id, None) + item = self._items_by_id.pop(item_id) + if item is not None: + parent = self.invisibleRootItem() + parent.removeRow(item.row()) def get_report_by_id(self, item_id): report_item = self._report_items_by_id.get(item_id) From 10125a40784e97e0a46f1e87063833ff98ccd7c2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 16:45:49 +0100 Subject: [PATCH 11/15] avoid usage of 'clear' method --- .../tools/publisher/publish_report_viewer/model.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/model.py b/openpype/tools/publisher/publish_report_viewer/model.py index 663a67ac70..9d3c90d18f 100644 --- a/openpype/tools/publisher/publish_report_viewer/model.py +++ b/openpype/tools/publisher/publish_report_viewer/model.py @@ -26,14 +26,15 @@ class InstancesModel(QtGui.QStandardItemModel): return self._items_by_id def set_report(self, report_item): - self.clear() + root_item = self.invisibleRootItem() + if root_item.rowCount(): + root_item.removeRows(0, root_item.rowCount()) + self._items_by_id.clear() self._plugin_items_by_id.clear() if not report_item: return - root_item = self.invisibleRootItem() - families = set(report_item.instance_items_by_family.keys()) families.remove(None) all_families = list(sorted(families)) @@ -125,14 +126,14 @@ class PluginsModel(QtGui.QStandardItemModel): return self._items_by_id def set_report(self, report_item): - self.clear() + root_item = self.invisibleRootItem() + if root_item.rowCount() > 0: + root_item.removeRows(0, root_item.rowCount()) self._items_by_id.clear() self._plugin_items_by_id.clear() if not report_item: return - root_item = self.invisibleRootItem() - labels_iter = iter(self.order_label_mapping) cur_order, cur_label = next(labels_iter) cur_plugin_items = [] From 79f592aaf375282892d5e5e9e4951073e28bd482 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 16:52:29 +0100 Subject: [PATCH 12/15] fix 'pop' of item by id --- openpype/tools/publisher/publish_report_viewer/window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 283d6284d6..8422f3aeab 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -438,7 +438,7 @@ class LoadedFilesModel(QtGui.QStandardItemModel): self._handler.remove_report_item(item_id) self._report_items_by_id.pop(item_id, None) - item = self._items_by_id.pop(item_id) + item = self._items_by_id.pop(item_id, None) if item is not None: parent = self.invisibleRootItem() parent.removeRow(item.row()) From 3d7e02a550c70ffa07e68c7c4c0950431681707f Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 18:21:41 +0100 Subject: [PATCH 13/15] use utc isoformat with help of 'arrow' --- openpype/tools/publisher/control.py | 5 +++-- .../publisher/publish_report_viewer/window.py | 17 +++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 125d93b6fd..23456579ca 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -11,6 +11,7 @@ import inspect from abc import ABCMeta, abstractmethod import six +import arrow import pyblish.api from openpype import AYON_SERVER_ENABLED @@ -287,7 +288,7 @@ class PublishReportMaker: def get_report(self, publish_plugins=None): """Report data with all details of current state.""" - now = datetime.datetime.now() + now = arrow.utcnow().to("local") instances_details = {} for instance in self._all_instances_by_id.values(): instances_details[instance.id] = self._extract_instance_data( @@ -337,7 +338,7 @@ class PublishReportMaker: "context": self._extract_context_data(self._current_context), "crashed_file_paths": crashed_file_paths, "id": uuid.uuid4().hex, - "created_at": now.strftime("%Y-%m-%d %H:%M:%S"), + "created_at": now.isoformat(), "report_version": "1.0.1", } diff --git a/openpype/tools/publisher/publish_report_viewer/window.py b/openpype/tools/publisher/publish_report_viewer/window.py index 8422f3aeab..f9c8c05802 100644 --- a/openpype/tools/publisher/publish_report_viewer/window.py +++ b/openpype/tools/publisher/publish_report_viewer/window.py @@ -2,9 +2,9 @@ import os import json import six import uuid -import datetime import appdirs +import arrow from qtpy import QtWidgets, QtCore, QtGui from openpype import style @@ -56,10 +56,8 @@ class PublishReportItem: if os.path.exists(report_path): file_modified = os.path.getmtime(report_path) - created_at_obj = datetime.datetime.strptime( - content["created_at"], "%Y-%m-%d %H:%M:%S" - ) - created_at = created_at_obj.timestamp() + created_at_obj = arrow.get(content["created_at"]).to("local") + created_at = created_at_obj.float_timestamp self.content = content self.report_path = report_path @@ -243,10 +241,10 @@ class PublishReportItem: # Auto fix 'created_at', use file modification time if it is not set # or current time if modification could not be received. if file_modified is not None: - created_at_obj = datetime.datetime.fromtimestamp(file_modified) + created_at_obj = arrow.Arrow.fromtimestamp(file_modified) else: - created_at_obj = datetime.datetime.now() - content["created_at"] = created_at_obj.strftime("%Y-%m-%d %H:%M:%S") + created_at_obj = arrow.utcnow() + content["created_at"] = created_at_obj.to("local").isoformat() return True @@ -320,9 +318,8 @@ class LoadedFilesModel(QtGui.QStandardItemModel): def refresh(self): root_item = self.invisibleRootItem() - if root_item.rowCount(): + if root_item.rowCount() > 0: root_item.removeRows(0, root_item.rowCount()) - self._items_by_id = {} self._report_items_by_id = {} From 3a22c1dd154fc15409d1a80930861335e5a98b88 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 18:35:27 +0100 Subject: [PATCH 14/15] use explicit condition --- openpype/tools/publisher/publish_report_viewer/model.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/tools/publisher/publish_report_viewer/model.py b/openpype/tools/publisher/publish_report_viewer/model.py index 9d3c90d18f..460a269f1a 100644 --- a/openpype/tools/publisher/publish_report_viewer/model.py +++ b/openpype/tools/publisher/publish_report_viewer/model.py @@ -27,9 +27,8 @@ class InstancesModel(QtGui.QStandardItemModel): def set_report(self, report_item): root_item = self.invisibleRootItem() - if root_item.rowCount(): + if root_item.rowCount() > 0: root_item.removeRows(0, root_item.rowCount()) - self._items_by_id.clear() self._plugin_items_by_id.clear() if not report_item: From 53c593d41dae53d25c879ebcb4965c558278737b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Dec 2023 18:53:09 +0100 Subject: [PATCH 15/15] removed unused import --- openpype/tools/publisher/control.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 23456579ca..47e374edf2 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -4,7 +4,6 @@ import logging import traceback import collections import uuid -import datetime import tempfile import shutil import inspect