diff --git a/src/quadpype/hosts/blender/api/ops.py b/src/quadpype/hosts/blender/api/ops.py index d951d4c8fd..b45bf69d45 100644 --- a/src/quadpype/hosts/blender/api/ops.py +++ b/src/quadpype/hosts/blender/api/ops.py @@ -405,7 +405,7 @@ class TOPBAR_MT_avalon(bpy.types.Menu): """Avalon menu.""" bl_idname = "TOPBAR_MT_avalon" - bl_label = os.getenv("QUADPYPE_LABEL") + bl_label = os.getenv("QUADPYPE_LABEL") or "QuadPype" def draw(self, context): """Draw the menu in the UI.""" diff --git a/src/quadpype/hosts/flame/api/scripts/wiretap_com.py b/src/quadpype/hosts/flame/api/scripts/wiretap_com.py index 78bf9ac554..63d403b79d 100644 --- a/src/quadpype/hosts/flame/api/scripts/wiretap_com.py +++ b/src/quadpype/hosts/flame/api/scripts/wiretap_com.py @@ -1,14 +1,15 @@ #!/usr/bin/env python2.7 # -*- coding: utf-8 -*- - -from __future__ import absolute_import import os import sys import subprocess import json + +from __future__ import absolute_import import xml.dom.minidom as minidom from copy import deepcopy -import datetime +from datetime import datetime, timezone + from libwiretapPythonClientAPI import ( # noqa WireTapClientInit, WireTapClientUninit, @@ -261,7 +262,7 @@ def _user_prep(self, user_name): return filtered_users.pop() # create new user name with date in suffix - now = datetime.datetime.now() # current date and time + now = datetime.now(timezone.utc) # current date and time date = now.strftime("%Y%m%d") new_user_name = "{}_{}".format(user_name, date) print(new_user_name) diff --git a/src/quadpype/hosts/harmony/api/server.py b/src/quadpype/hosts/harmony/api/server.py index a00c9aaf14..877f66f805 100644 --- a/src/quadpype/hosts/harmony/api/server.py +++ b/src/quadpype/hosts/harmony/api/server.py @@ -8,8 +8,10 @@ import functools import time import struct -from datetime import datetime import threading + +from datetime import datetime, timezone + from . import lib @@ -170,18 +172,18 @@ def run(self): Waits for a connection on `self.port` before going into listen mode. """ # Wait for a connection - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") self.log.debug(f"[{timestamp}] Waiting for a connection.") self.connection, client_address = self.socket.accept() - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") self.log.debug(f"[{timestamp}] Connection from: {client_address}") self.receive() def stop(self): """Shutdown socket server gracefully.""" - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") self.log.debug(f"[{timestamp}] Shutting down server.") if self.connection is None: self.log.debug("Connect to shutdown.") @@ -204,7 +206,7 @@ def _send(self, message): while not self.connection: pass - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") encoded = message.encode("utf-8") coded_message = b"AH" + struct.pack('>I', len(encoded)) + encoded pretty = self._pretty(coded_message) @@ -225,7 +227,7 @@ def send(self, request): request["message_id"] = self.message_id self._send(json.dumps(request)) if request.get("reply"): - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") self.log.debug( f"[{timestamp}] sent reply, not waiting for anything.") return None @@ -235,7 +237,7 @@ def send(self, request): while True: time.sleep(0.1) if time.time() > current_time + 30: - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") self.log.error((f"[{timestamp}][{self.message_id}] " "No reply from Harmony in 30s. " f"Retrying {try_index}")) @@ -245,7 +247,7 @@ def send(self, request): break try: result = self.queue[request["message_id"]] - timestamp = datetime.now().strftime("%H:%M:%S.%f") + timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f") self.log.debug((f"[{timestamp}] Got request " f"id {self.message_id}, " "removing from queue")) @@ -276,4 +278,4 @@ def timestamp(self): str: current timestamp. """ - return datetime.now().strftime("%H:%M:%S.%f") + return datetime.now(timezone.utc).strftime("%H:%M:%S.%f") diff --git a/src/quadpype/hosts/nuke/vendor/google/protobuf/internal/well_known_types.py b/src/quadpype/hosts/nuke/vendor/google/protobuf/internal/well_known_types.py index b581ab750a..5c8fc6db11 100644 --- a/src/quadpype/hosts/nuke/vendor/google/protobuf/internal/well_known_types.py +++ b/src/quadpype/hosts/nuke/vendor/google/protobuf/internal/well_known_types.py @@ -42,7 +42,8 @@ import calendar import collections.abc -import datetime + +from datetime import datetime, timezone, timedelta from google.protobuf.descriptor import FieldDescriptor @@ -160,8 +161,8 @@ def FromJsonString(self, value): raise ValueError( 'time data \'{0}\' does not match format \'%Y-%m-%dT%H:%M:%S\', ' 'lowercase \'t\' is not accepted'.format(second_value)) - date_object = datetime.datetime.strptime(second_value, _TIMESTAMPFOMAT) - td = date_object - datetime.datetime(1970, 1, 1) + date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT) + td = date_object - datetime(1970, 1, 1) seconds = td.seconds + td.days * _SECONDS_PER_DAY if len(nano_value) > 9: raise ValueError( @@ -192,7 +193,7 @@ def FromJsonString(self, value): def GetCurrentTime(self): """Get the current UTC into Timestamp.""" - self.FromDatetime(datetime.datetime.utcnow()) + self.FromDatetime(datetime.now(timezone.utc)) def ToNanoseconds(self): """Converts Timestamp to nanoseconds since epoch.""" @@ -244,7 +245,7 @@ def ToDatetime(self, tzinfo=None): Otherwise, returns a timezone-aware datetime in the input timezone. """ - delta = datetime.timedelta( + delta = timedelta( seconds=self.seconds, microseconds=_RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND)) if tzinfo is None: @@ -382,7 +383,7 @@ def FromSeconds(self, seconds): def ToTimedelta(self): """Converts Duration to timedelta.""" - return datetime.timedelta( + return timedelta( seconds=self.seconds, microseconds=_RoundTowardZero( self.nanos, _NANOS_PER_MICROSECOND)) diff --git a/src/quadpype/hosts/webpublisher/lib.py b/src/quadpype/hosts/webpublisher/lib.py index 9e2d14df58..e15047f215 100644 --- a/src/quadpype/hosts/webpublisher/lib.py +++ b/src/quadpype/hosts/webpublisher/lib.py @@ -1,8 +1,9 @@ import os -from datetime import datetime import collections import json +from datetime import datetime, timezone + from bson.objectid import ObjectId import pyblish.util @@ -125,7 +126,7 @@ def start_webpublish_log(dbcon, batch_id, user): """ return dbcon.insert_one({ "batch_id": batch_id, - "start_date": datetime.now(), + "start_date": datetime.now(timezone.utc), "user": user, "status": IN_PROGRESS_STATUS, "progress": 0 # integer 0-100, percentage @@ -168,7 +169,7 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): {"_id": _id}, {"$set": { - "finish_date": datetime.now(), + "finish_date": datetime.now(timezone.utc), "status": ERROR_STATUS, "log": os.linesep.join(log_lines) @@ -197,7 +198,7 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): { "$set": { - "finish_date": datetime.now(), + "finish_date": datetime.now(timezone.utc), "status": FINISHED_REPROCESS_STATUS, } } @@ -208,7 +209,7 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): { "$set": { - "finish_date": datetime.now(), + "finish_date": datetime.now(timezone.utc), "status": FINISHED_OK_STATUS, "progress": 100, "log": os.linesep.join(log_lines) @@ -227,7 +228,7 @@ def fail_batch(_id, dbcon, msg): {"_id": _id}, {"$set": { - "finish_date": datetime.now(), + "finish_date": datetime.now(timezone.utc), "status": ERROR_STATUS, "log": msg diff --git a/src/quadpype/hosts/webpublisher/webserver_service/webpublish_routes.py b/src/quadpype/hosts/webpublisher/webserver_service/webpublish_routes.py index b3d27556ef..ea7ff211d9 100644 --- a/src/quadpype/hosts/webpublisher/webserver_service/webpublish_routes.py +++ b/src/quadpype/hosts/webpublisher/webserver_service/webpublish_routes.py @@ -1,9 +1,11 @@ """Routes and etc. for webpublisher API.""" import os import json -import datetime import collections import subprocess + +from datetime import datetime + from bson.objectid import ObjectId from fastapi import Response, status @@ -44,7 +46,7 @@ class JsonApiResource: """ @staticmethod def json_dump_handler(value): - if isinstance(value, datetime.datetime): + if isinstance(value, datetime): return value.isoformat() if isinstance(value, ObjectId): return str(value) diff --git a/src/quadpype/hosts/webpublisher/webserver_service/webserver.py b/src/quadpype/hosts/webpublisher/webserver_service/webserver.py index bef2440102..ac141cbad5 100644 --- a/src/quadpype/hosts/webpublisher/webserver_service/webserver.py +++ b/src/quadpype/hosts/webpublisher/webserver_service/webserver.py @@ -1,7 +1,7 @@ import collections import time import os -from datetime import datetime +from datetime import datetime, timezone import requests import json import subprocess @@ -147,7 +147,7 @@ def reprocess_failed(upload_dir, webserver_url): {"_id": batch["_id"]}, {"$set": { - "finish_date": datetime.now(), + "finish_date": datetime.now(timezone.utc), "status": ERROR_STATUS, "progress": 100, "log": batch.get("log") + msg @@ -166,7 +166,7 @@ def reprocess_failed(upload_dir, webserver_url): }, { "$set": { - "finish_date": datetime.now(), + "finish_date": datetime.now(timezone.utc), "status": SENT_REPROCESSING_STATUS, "progress": 100 } diff --git a/src/quadpype/lib/cache.py b/src/quadpype/lib/cache.py index 023c296335..4846630ee3 100644 --- a/src/quadpype/lib/cache.py +++ b/src/quadpype/lib/cache.py @@ -2,7 +2,8 @@ """Module storing class for caching values, used for settings.""" import json import copy -import datetime + +from datetime import datetime, timezone class CacheValues: @@ -21,7 +22,7 @@ def data_copy(self): def update_data(self, data, version): self.data = data - self.creation_time = datetime.datetime.now() + self.creation_time = datetime.now(timezone.utc) self.version = version def update_last_saved_info(self, last_saved_info): @@ -47,7 +48,7 @@ def to_json_string(self): def is_outdated(self): if self.creation_time is None: return True - delta = (datetime.datetime.now() - self.creation_time).seconds + delta = (datetime.now(timezone.utc) - self.creation_time).seconds return delta > self.cache_lifetime def set_outdated(self): diff --git a/src/quadpype/lib/dateutils.py b/src/quadpype/lib/dateutils.py index b00cdd012b..c88644ad8c 100644 --- a/src/quadpype/lib/dateutils.py +++ b/src/quadpype/lib/dateutils.py @@ -35,7 +35,7 @@ def get_datetime_data(datetime_obj=None): """ if not datetime_obj: - datetime_obj = datetime.now() + datetime_obj = datetime.now(timezone.utc) year = datetime_obj.strftime("%Y") @@ -80,7 +80,7 @@ def get_timestamp_str(datetime_obj=None, local_timezone=False): """Get standardized timestamp string from a datetime object. Args: - datetime_obj (datetime.datetime): Object of datetime. Current time + datetime_obj (datetime): Object of datetime. Current time is used if not passed. """ diff --git a/src/quadpype/lib/log.py b/src/quadpype/lib/log.py index 0b46c97e51..94807ca297 100644 --- a/src/quadpype/lib/log.py +++ b/src/quadpype/lib/log.py @@ -10,9 +10,6 @@ Best place for it is in ``repos/pype-config/environments/global.json`` """ - - -import datetime import getpass import logging import os @@ -24,6 +21,8 @@ import threading import copy +from datetime import datetime, timezone + from quadpype.client.mongo import ( MongoEnvNotSet, get_default_components, @@ -131,7 +130,7 @@ def format(self, record): """Formats LogRecord into python dictionary.""" # Standard document document = { - 'timestamp': datetime.datetime.now(), + 'timestamp': datetime.now(timezone.utc), 'level': record.levelname, 'thread': record.thread, 'threadName': record.threadName, diff --git a/src/quadpype/lib/project_backpack.py b/src/quadpype/lib/project_backpack.py index 342af6789b..cdb179a9a7 100644 --- a/src/quadpype/lib/project_backpack.py +++ b/src/quadpype/lib/project_backpack.py @@ -19,9 +19,10 @@ import platform import tempfile import shutil -import datetime - import zipfile + +from datetime import datetime, timezone + from quadpype.client.mongo import ( load_json_file, get_project_connection, @@ -37,7 +38,7 @@ def add_timestamp(filepath): """Add timestamp string to a file.""" base, ext = os.path.splitext(filepath) - timestamp = datetime.datetime.now().strftime("%y%m%d_%H%M%S") + timestamp = datetime.now(timezone.utc).strftime("%y%m%d_%H%M%S") new_base = "{}_{}".format(base, timestamp) return new_base + ext diff --git a/src/quadpype/lib/pype_info.py b/src/quadpype/lib/pype_info.py index 5496a20cfc..b41f0a2676 100644 --- a/src/quadpype/lib/pype_info.py +++ b/src/quadpype/lib/pype_info.py @@ -1,6 +1,6 @@ import os import json -import datetime +from datetime import datetime, timezone from .execute import get_quadpype_execute_args from .user import get_user_id, get_user_profile @@ -58,7 +58,7 @@ def extract_pype_info_to_file(dir_path): filename = "{}_{}_{}.json".format( get_quadpype_version(), get_user_id(), - datetime.datetime.now().strftime("%y%m%d%H%M%S") + datetime.now(timezone.utc).strftime("%y%m%d%H%M%S") ) filepath = os.path.join(dir_path, filename) data = get_all_current_info() diff --git a/src/quadpype/lib/registry.py b/src/quadpype/lib/registry.py index a5d35222b4..21b211954b 100644 --- a/src/quadpype/lib/registry.py +++ b/src/quadpype/lib/registry.py @@ -3,7 +3,7 @@ import os import json import platform -from datetime import datetime +from datetime import datetime, timezone from abc import ABC, abstractmethod from functools import lru_cache import configparser @@ -227,7 +227,7 @@ def __init__(self, name, path): with open(self._registry_file, mode="w") as cfg: print("# Settings registry", cfg) print("# Generated by QuadPype {}".format(version), cfg) - now = datetime.now().strftime("%d/%m/%Y %H:%M:%S") + now = datetime.now(timezone.utc).strftime("%d/%m/%Y %H:%M:%S") print("# {}".format(now), cfg) def set_item_section( @@ -376,7 +376,7 @@ def __init__(self, name, path, base_version=None): super(JSONSettingRegistry, self).__init__(name) #: str: name of registry file self._registry_file = os.path.join(path, "{}.json".format(name)) - now = datetime.now().strftime("%d/%m/%Y %H:%M:%S") + now = datetime.now(timezone.utc).strftime("%d/%m/%Y %H:%M:%S") if not base_version: base_version = "N/A" diff --git a/src/quadpype/lib/user.py b/src/quadpype/lib/user.py index 3007396000..16ae91e5fc 100644 --- a/src/quadpype/lib/user.py +++ b/src/quadpype/lib/user.py @@ -3,10 +3,11 @@ import os import copy import getpass -import datetime import functools import platform import socket + +from datetime import datetime, timezone from abc import ABC, abstractmethod from .registry import get_app_registry @@ -27,8 +28,8 @@ class UserHandler(ABC): user_profile_template = { "user_id": "", "role": "user", - "first_connection_timestamp": datetime.datetime.now(), - "last_connection_timestamp": datetime.datetime.now(), + "first_connection_timestamp": datetime.now(timezone.utc), + "last_connection_timestamp": datetime.now(timezone.utc), "last_workstation_profile_index": 0, "workstation_profiles": [], "settings": {} @@ -103,7 +104,7 @@ def create_user_profile(self, user_role="user"): user_profile["user_id"] = self.user_id user_profile["role"] = user_role - timestamp = datetime.datetime.now() + timestamp = datetime.now(timezone.utc) user_profile["first_connection_timestamp"] = timestamp user_profile["last_connection_timestamp"] = timestamp @@ -131,7 +132,7 @@ def get_all_user_profiles(self): def update_user_profile_on_startup(self): """Update user profile on startup""" user_profile = self.get_user_profile() - user_profile["last_connection_timestamp"] = datetime.datetime.now() + user_profile["last_connection_timestamp"] = datetime.now(timezone.utc) workstation_info = get_user_workstation_info() diff --git a/src/quadpype/modules/base.py b/src/quadpype/modules/base.py index d1920be3cb..34e9f83b71 100644 --- a/src/quadpype/modules/base.py +++ b/src/quadpype/modules/base.py @@ -1155,7 +1155,6 @@ class TrayModulesManager(ModulesManager): "clockify", # Clockify "sync_server", # Sync Queue # More Tools Submenu ----------------------------- - "update_zxp_extensions", # Update ZXP Extensions "log_viewer", # Show Logs "python_interpreter", # Console # Admin Submenu ---------------------------------- diff --git a/src/quadpype/modules/clockify/clockify_api.py b/src/quadpype/modules/clockify/clockify_api.py index 2b57958d14..4aea8c0a02 100644 --- a/src/quadpype/modules/clockify/clockify_api.py +++ b/src/quadpype/modules/clockify/clockify_api.py @@ -1,6 +1,8 @@ import os import json -import datetime + +from datetime import datetime, timezone + import requests from .constants import ( CLOCKIFY_ENDPOINT, @@ -221,7 +223,7 @@ def get_task_id(self, task_name, project_id, workspace_id=None): return all_tasks[task_name] def get_current_time(self): - return str(datetime.datetime.utcnow().isoformat()) + "Z" + return datetime.now(timezone.utc).isoformat() def start_time_entry( self, diff --git a/src/quadpype/modules/deadline/aftereffects/publish/submit_aftereffects_deadline.py b/src/quadpype/modules/deadline/aftereffects/publish/submit_aftereffects_deadline.py index fb9bef99ca..be43a1f6a9 100644 --- a/src/quadpype/modules/deadline/aftereffects/publish/submit_aftereffects_deadline.py +++ b/src/quadpype/modules/deadline/aftereffects/publish/submit_aftereffects_deadline.py @@ -2,7 +2,8 @@ import attr import getpass import pyblish.api -from datetime import datetime + +from datetime import datetime, timezone from quadpype.lib import ( env_value_to_bool, @@ -65,7 +66,7 @@ def get_job_info(self): ) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") dln_job_info.Name = job_name dln_job_info.BatchName = "Group: " + batch_name dln_job_info.Plugin = "AfterEffects" diff --git a/src/quadpype/modules/deadline/blender/publish/submit_blender_deadline.py b/src/quadpype/modules/deadline/blender/publish/submit_blender_deadline.py index 51a87fd8b6..d6ac36694a 100644 --- a/src/quadpype/modules/deadline/blender/publish/submit_blender_deadline.py +++ b/src/quadpype/modules/deadline/blender/publish/submit_blender_deadline.py @@ -4,7 +4,8 @@ import os import getpass import attr -from datetime import datetime + +from datetime import datetime, timezone from quadpype.lib import ( is_running_from_build, @@ -58,7 +59,7 @@ def get_job_info(self): src_filename = os.path.basename(src_filepath) if is_in_tests(): - src_filename += datetime.now().strftime("%d%m%Y%H%M%S") + src_filename += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") job_info.Name = f"{src_filename} - {instance.name}" job_info.BatchName = src_filename diff --git a/src/quadpype/modules/deadline/harmony/publish/submit_harmony_deadline.py b/src/quadpype/modules/deadline/harmony/publish/submit_harmony_deadline.py index 79b77e05c9..1cd41efab5 100644 --- a/src/quadpype/modules/deadline/harmony/publish/submit_harmony_deadline.py +++ b/src/quadpype/modules/deadline/harmony/publish/submit_harmony_deadline.py @@ -5,7 +5,8 @@ from collections import OrderedDict from zipfile import ZipFile, is_zipfile import re -from datetime import datetime + +from datetime import datetime, timezone import attr import pyblish.api @@ -276,7 +277,7 @@ def get_job_info(self): "deadline_batch_name" ) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") job_info.BatchName = "Group: " + batch_name job_info.Name = job_name job_info.BatchName = batch_name diff --git a/src/quadpype/modules/deadline/houdini/publish/submit_houdini_cache_deadline.py b/src/quadpype/modules/deadline/houdini/publish/submit_houdini_cache_deadline.py index 36131d88cb..0ecbdc47ff 100644 --- a/src/quadpype/modules/deadline/houdini/publish/submit_houdini_cache_deadline.py +++ b/src/quadpype/modules/deadline/houdini/publish/submit_houdini_cache_deadline.py @@ -1,6 +1,7 @@ import os import getpass -from datetime import datetime + +from datetime import datetime, timezone import attr import pyblish.api @@ -80,7 +81,7 @@ def get_job_info(self): batch_name = "{code} - {scene}".format(code=project_name, scene=scenename) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") job_info.Name = job_name job_info.BatchName = batch_name diff --git a/src/quadpype/modules/deadline/houdini/publish/submit_houdini_remote_publish.py b/src/quadpype/modules/deadline/houdini/publish/submit_houdini_remote_publish.py index a2c51866ac..6f2d91724b 100644 --- a/src/quadpype/modules/deadline/houdini/publish/submit_houdini_remote_publish.py +++ b/src/quadpype/modules/deadline/houdini/publish/submit_houdini_remote_publish.py @@ -1,7 +1,8 @@ import os import json import getpass -from datetime import datetime + +from datetime import datetime, timezone import requests @@ -72,7 +73,7 @@ def process(self, context): job_name = "{scene} [PUBLISH]".format(scene=scenename) batch_name = "{code} - {scene}".format(code=code, scene=scenename) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") deadline_user = context.data.get("deadlineUser", getpass.getuser()) # Get only major.minor version of Houdini, ignore patch version diff --git a/src/quadpype/modules/deadline/houdini/publish/submit_houdini_render_deadline.py b/src/quadpype/modules/deadline/houdini/publish/submit_houdini_render_deadline.py index e971734638..a48f1cb610 100644 --- a/src/quadpype/modules/deadline/houdini/publish/submit_houdini_render_deadline.py +++ b/src/quadpype/modules/deadline/houdini/publish/submit_houdini_render_deadline.py @@ -1,7 +1,8 @@ import os import attr import getpass -from datetime import datetime + +from datetime import datetime, timezone import pyblish.api @@ -182,7 +183,7 @@ def get_job_info(self, dependency_job_ids=None): "deadlineUser", getpass.getuser()) if is_in_tests(): - job_info.BatchName += datetime.now().strftime("%d%m%Y%H%M%S") + job_info.BatchName += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") # Deadline requires integers in frame range start = instance.data["frameStartHandle"] diff --git a/src/quadpype/modules/deadline/maya/publish/submit_maya_deadline.py b/src/quadpype/modules/deadline/maya/publish/submit_maya_deadline.py index add4982ced..2171d0fe80 100644 --- a/src/quadpype/modules/deadline/maya/publish/submit_maya_deadline.py +++ b/src/quadpype/modules/deadline/maya/publish/submit_maya_deadline.py @@ -22,7 +22,7 @@ import copy import re import hashlib -from datetime import datetime +from datetime import datetime, timezone import itertools from collections import OrderedDict @@ -155,7 +155,7 @@ def get_job_info(self): ) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") job_info.Name = job_name job_info.BatchName = "Group: " + batch_name @@ -498,7 +498,7 @@ def _tile_render(self, payload): output_dir, "{}_config_{}.txt".format( os.path.splitext(file)[0], - datetime.now().strftime("%Y_%m_%d_%H_%M_%S") + datetime.now(timezone.utc).strftime("%Y_%m_%d_%H_%M_%S") ) ) config_files.append(config_file) diff --git a/src/quadpype/modules/deadline/maya/publish/submit_maya_remote_publish_deadline.py b/src/quadpype/modules/deadline/maya/publish/submit_maya_remote_publish_deadline.py index 33fe7dedd8..816c089f8c 100644 --- a/src/quadpype/modules/deadline/maya/publish/submit_maya_remote_publish_deadline.py +++ b/src/quadpype/modules/deadline/maya/publish/submit_maya_remote_publish_deadline.py @@ -1,6 +1,7 @@ import os import attr -from datetime import datetime + +from datetime import datetime, timezone from quadpype.settings import PROJECT_SETTINGS_KEY from quadpype.pipeline import legacy_io, PublishXmlValidationError @@ -90,7 +91,7 @@ def get_job_info(self): ) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") job_info = DeadlineJobInfo(Plugin="MayaBatch") job_info.BatchName = "Group: " + batch_name, diff --git a/src/quadpype/modules/deadline/nuke/publish/submit_nuke_deadline.py b/src/quadpype/modules/deadline/nuke/publish/submit_nuke_deadline.py index 2df581ce07..810915e60a 100644 --- a/src/quadpype/modules/deadline/nuke/publish/submit_nuke_deadline.py +++ b/src/quadpype/modules/deadline/nuke/publish/submit_nuke_deadline.py @@ -3,7 +3,8 @@ import json import getpass import platform -from datetime import datetime + +from datetime import datetime, timezone import requests import pyblish.api @@ -322,7 +323,7 @@ def payload_submit( ) if is_in_tests(): - batch_name += datetime.now().strftime("%d%m%Y%H%M%S") + batch_name += datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") output_filename_0 = self.preview_fname(render_path) diff --git a/src/quadpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/src/quadpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index f987870beb..9a13a85c3b 100644 --- a/src/quadpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/src/quadpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -2,17 +2,17 @@ # -*- coding: utf-8 -*- import os import tempfile -from datetime import datetime +from datetime import datetime, timezone import subprocess import json import platform import uuid import re + from Deadline.Scripting import ( RepositoryUtils, FileUtils, - DirectoryUtils, - ProcessUtils, + DirectoryUtils ) VERSION_REGEX = re.compile( @@ -323,7 +323,7 @@ def inject_quadpype_environment(deadlinePlugin): # tempfile.TemporaryFile cannot be used because of locking temp_file_name = "{}_{}.json".format( - datetime.utcnow().strftime('%Y%m%d%H%M%S%f'), + datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S%f'), str(uuid.uuid1()) ) export_url = os.path.join(tempfile.gettempdir(), temp_file_name) diff --git a/src/quadpype/modules/ftrack/event_handlers_server/action_create_review_session.py b/src/quadpype/modules/ftrack/event_handlers_server/action_create_review_session.py index e7c9624181..cdd01cce30 100644 --- a/src/quadpype/modules/ftrack/event_handlers_server/action_create_review_session.py +++ b/src/quadpype/modules/ftrack/event_handlers_server/action_create_review_session.py @@ -1,8 +1,9 @@ import threading -import datetime import copy import collections +from datetime import datetime, timezone, timedelta + import ftrack_api from quadpype.lib import get_datetime_data @@ -46,7 +47,7 @@ def __init__(self, *args, **kwargs): self._cycle_timer = None self._last_cyle_time = None - self._day_delta = datetime.timedelta(days=1) + self._day_delta = timedelta(days=1) def discover(self, session, entities, event): """Show action only on AssetVersions.""" @@ -99,11 +100,9 @@ def _calculate_next_cycle_delta(self): # Create threading timer which will trigger creation of report # at the 00:00:01 of next day # - callback will trigger another timer which will have 1 day offset - now = datetime.datetime.now() + now = datetime.now(timezone.utc) # Create object of today morning - expected_next_trigger = datetime.datetime( - now.year, now.month, now.day, h, m, s - ) + expected_next_trigger = datetime(now.year, now.month, now.day, h, m, s, tzinfo=timezone.utc) if expected_next_trigger > now: seconds = (expected_next_trigger - now).total_seconds() else: @@ -199,10 +198,8 @@ def _process_review_session( review_sessions_by_project_id[project_id].append(review_session) # Prepare fill data for today's review sesison and yesterdays - now = datetime.datetime.now() - today_obj = datetime.datetime( - now.year, now.month, now.day, 0, 0, 0 - ) + now = datetime.now(timezone.utc) + today_obj = datetime(now.year, now.month, now.day, 0, 0, 0, tzinfo=timezone.utc) yesterday_obj = today_obj - self._day_delta today_fill_data = get_datetime_data(today_obj) diff --git a/src/quadpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py b/src/quadpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py index bfb4936561..4211818886 100644 --- a/src/quadpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py +++ b/src/quadpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py @@ -2,10 +2,11 @@ import copy import json import time -import datetime import atexit import traceback +from datetime import datetime, timezone + from bson.objectid import ObjectId from pymongo import UpdateOne @@ -85,7 +86,7 @@ def __init__(self, session): # - time expiration in seconds self.debug_print_time_expiration = 5 * 60 # - store current time - self.debug_print_time = datetime.datetime.now() + self.debug_print_time = datetime.now(timezone.utc) # - store synchronize entity types to be able to use # only entityTypes in interest instead of filtering by ignored self.debug_sync_types = collections.defaultdict(list) @@ -97,7 +98,7 @@ def __init__(self, session): def debug_logs(self): """This is debug method for printing small debugs messages. """ - now_datetime = datetime.datetime.now() + now_datetime = datetime.now(timezone.utc) delta = now_datetime - self.debug_print_time if delta.total_seconds() < self.debug_print_time_expiration: return diff --git a/src/quadpype/modules/ftrack/event_handlers_user/action_delete_asset.py b/src/quadpype/modules/ftrack/event_handlers_user/action_delete_asset.py index 64a3901c50..5555edfd6b 100644 --- a/src/quadpype/modules/ftrack/event_handlers_user/action_delete_asset.py +++ b/src/quadpype/modules/ftrack/event_handlers_user/action_delete_asset.py @@ -1,6 +1,6 @@ import collections import uuid -from datetime import datetime +from datetime import datetime, timezone from bson.objectid import ObjectId @@ -181,7 +181,7 @@ def interface(self, session, entities, event): if not created_at: old_action_ids.append(action_id) continue - cur_time = datetime.now() + cur_time = datetime.now(timezone.utc) existing_in_sec = (created_at - cur_time).total_seconds() if existing_in_sec > 60 * 2: old_action_ids.append(action_id) @@ -193,7 +193,7 @@ def interface(self, session, entities, event): action_id = str(uuid.uuid1()) self.action_data_by_id[action_id] = { "attempt": 1, - "created_at": datetime.now(), + "created_at": datetime.now(timezone.utc), "project_name": project_name, "subset_ids_by_name": {}, "subset_ids_by_parent": {}, diff --git a/src/quadpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py b/src/quadpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py index f8790b46cc..4cfa0f448e 100644 --- a/src/quadpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py +++ b/src/quadpype/modules/ftrack/event_handlers_user/action_fill_workfile_attr.py @@ -3,7 +3,7 @@ import json import collections import tempfile -import datetime +from datetime import datetime, timezone import ftrack_api @@ -174,7 +174,7 @@ def launch(self, session, entities, event): component_name = "{}_{}".format( "FillWorkfilesReport", - datetime.datetime.now().strftime("%y-%m-%d-%H%M") + datetime.now(timezone.utc).strftime("%y-%m-%d-%H%M") ) self.add_file_component_to_job( job_entity, session, temp_filepath, component_name diff --git a/src/quadpype/modules/ftrack/ftrack_server/event_server_cli.py b/src/quadpype/modules/ftrack/ftrack_server/event_server_cli.py index c5dd545126..859c822b74 100644 --- a/src/quadpype/modules/ftrack/ftrack_server/event_server_cli.py +++ b/src/quadpype/modules/ftrack/ftrack_server/event_server_cli.py @@ -1,6 +1,5 @@ import os import signal -import datetime import subprocess import socket import json @@ -9,6 +8,8 @@ import time import uuid +from datetime import datetime, timezone + import ftrack_api import pymongo from quadpype.client.mongo import ( @@ -109,7 +110,7 @@ def legacy_server(ftrack_url): subproc = None subproc_path = "{}/sub_legacy_server.py".format(scripts_dir) - subproc_last_failed = datetime.datetime.now() + subproc_last_failed = datetime.now(timezone.utc) subproc_failed_count = 0 ftrack_accessible = False @@ -122,7 +123,7 @@ def legacy_server(ftrack_url): # Run threads only if Ftrack is accessible if not ftrack_accessible and not printed_ftrack_error: print("Can't access Ftrack {} <{}>".format( - ftrack_url, str(datetime.datetime.now()) + ftrack_url, str(datetime.now(timezone.utc)) )) if subproc is not None: if subproc.poll() is None: @@ -150,7 +151,7 @@ def legacy_server(ftrack_url): ).format(str(max_fail_count), str(wait_time_after_max_fail))) subproc_failed_count += 1 elif (( - datetime.datetime.now() - subproc_last_failed + datetime.now(timezone.utc) - subproc_last_failed ).seconds > wait_time_after_max_fail): subproc_failed_count = 0 @@ -159,7 +160,7 @@ def legacy_server(ftrack_url): subproc = None ftrack_accessible = False - _subproc_last_failed = datetime.datetime.now() + _subproc_last_failed = datetime.now(timezone.utc) delta_time = (_subproc_last_failed - subproc_last_failed).seconds if delta_time < min_fail_seconds: subproc_failed_count += 1 @@ -197,21 +198,21 @@ def main_loop(ftrack_url): storer_port = 10001 storer_path = "{}/sub_event_storer.py".format(scripts_dir) storer_thread = None - storer_last_failed = datetime.datetime.now() + storer_last_failed = datetime.now(timezone.utc) storer_failed_count = 0 processor_name = "ProcessorThread" processor_port = 10011 processor_path = "{}/sub_event_processor.py".format(scripts_dir) processor_thread = None - processor_last_failed = datetime.datetime.now() + processor_last_failed = datetime.now(timezone.utc) processor_failed_count = 0 statuser_name = "StorerThread" statuser_port = 10021 statuser_path = "{}/sub_event_status.py".format(scripts_dir) statuser_thread = None - statuser_last_failed = datetime.datetime.now() + statuser_last_failed = datetime.now(timezone.utc) statuser_failed_count = 0 ftrack_accessible = False @@ -249,7 +250,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): host_ip = get_host_ip() main_info = [ - ["created_at", datetime.datetime.now().strftime("%Y.%m.%d %H:%M:%S")], + ["created_at", datetime.now(timezone.utc).strftime("%Y.%m.%d %H:%M:%S")], ["Username", getpass.getuser()], ["Host Name", host_name], ["Host IP", host_ip or "N/A"], @@ -311,7 +312,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): statuser_failed_count += 1 elif (( - datetime.datetime.now() - statuser_last_failed + datetime.now(timezone.utc) - statuser_last_failed ).seconds > wait_time_after_max_fail): statuser_failed_count = 0 @@ -322,7 +323,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): ftrack_accessible = False mongo_accessible = False - _processor_last_failed = datetime.datetime.now() + _processor_last_failed = datetime.now(timezone.utc) delta_time = ( _processor_last_failed - statuser_last_failed ).seconds @@ -354,7 +355,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): ).format(str(max_fail_count), str(wait_time_after_max_fail))) storer_failed_count += 1 elif (( - datetime.datetime.now() - storer_last_failed + datetime.now(timezone.utc) - storer_last_failed ).seconds > wait_time_after_max_fail): storer_failed_count = 0 @@ -367,7 +368,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): ftrack_accessible = False mongo_accessible = False - _storer_last_failed = datetime.datetime.now() + _storer_last_failed = datetime.now(timezone.utc) delta_time = (_storer_last_failed - storer_last_failed).seconds if delta_time < min_fail_seconds: storer_failed_count += 1 @@ -391,7 +392,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): processor_failed_count += 1 elif (( - datetime.datetime.now() - processor_last_failed + datetime.now(timezone.utc) - processor_last_failed ).seconds > wait_time_after_max_fail): processor_failed_count = 0 @@ -406,7 +407,7 @@ def on_exit(processor_thread, storer_thread, statuser_thread): ftrack_accessible = False mongo_accessible = False - _processor_last_failed = datetime.datetime.now() + _processor_last_failed = datetime.now(timezone.utc) delta_time = ( _processor_last_failed - processor_last_failed ).seconds diff --git a/src/quadpype/modules/ftrack/ftrack_server/lib.py b/src/quadpype/modules/ftrack/ftrack_server/lib.py index f3f4f9ada8..7cd9ce45e7 100644 --- a/src/quadpype/modules/ftrack/ftrack_server/lib.py +++ b/src/quadpype/modules/ftrack/ftrack_server/lib.py @@ -4,13 +4,14 @@ import getpass import atexit import threading -import datetime import time import queue import collections import appdirs import socket +from datetime import datetime, timezone, timedelta + import pymongo import requests import ftrack_api @@ -186,7 +187,7 @@ def wait(self, duration=None): def load_events(self): """Load not processed events sorted by stored date""" - ago_date = datetime.datetime.now() - datetime.timedelta(days=3) + ago_date = datetime.now(timezone.utc) - timedelta(days=3) self.dbcon.delete_many({ "pype_data.stored": {"$lte": ago_date}, "pype_data.is_processed": True diff --git a/src/quadpype/modules/ftrack/lib/ftrack_base_handler.py b/src/quadpype/modules/ftrack/lib/ftrack_base_handler.py index fbd896da21..fa985472dc 100644 --- a/src/quadpype/modules/ftrack/lib/ftrack_base_handler.py +++ b/src/quadpype/modules/ftrack/lib/ftrack_base_handler.py @@ -3,9 +3,11 @@ import json import functools import uuid -import datetime import traceback import time + +from datetime import datetime, timezone + from quadpype.lib import Logger from quadpype.settings import get_project_settings, PROJECT_SETTINGS_KEY @@ -670,7 +672,7 @@ def add_traceback_to_job( if not component_name: component_name = "{}_{}".format( cls.__name__, - datetime.datetime.now().strftime("%y-%m-%d-%H%M") + datetime.now(timezone.utc).strftime("%y-%m-%d-%H%M") ) cls.add_file_component_to_job( job, session, temp_filepath, component_name diff --git a/src/quadpype/modules/ftrack/scripts/sub_event_processor.py b/src/quadpype/modules/ftrack/scripts/sub_event_processor.py index ccd858deea..89916657a9 100644 --- a/src/quadpype/modules/ftrack/scripts/sub_event_processor.py +++ b/src/quadpype/modules/ftrack/scripts/sub_event_processor.py @@ -2,7 +2,8 @@ import sys import signal import socket -import datetime + +from datetime import datetime, timezone import ftrack_api @@ -20,7 +21,7 @@ get_build_version ) -subprocess_started = datetime.datetime.now() +subprocess_started = datetime.now(timezone.utc) class SessionFactory: diff --git a/src/quadpype/modules/ftrack/scripts/sub_event_status.py b/src/quadpype/modules/ftrack/scripts/sub_event_status.py index 2dab38f3ea..54be2f0709 100644 --- a/src/quadpype/modules/ftrack/scripts/sub_event_status.py +++ b/src/quadpype/modules/ftrack/scripts/sub_event_status.py @@ -5,7 +5,8 @@ import collections import signal import socket -import datetime + +from datetime import datetime, timezone import appdirs @@ -61,7 +62,7 @@ def __init__(self, name, label, parent): self.last_update = None def update(self, info): - self.last_update = datetime.datetime.now() + self.last_update = datetime.now(timezone.utc) self.info = info def get_delta_string(self, delta): @@ -87,7 +88,7 @@ def get_items(self): items = [] last_update = "N/A" if self.last_update: - delta = datetime.datetime.now() - self.last_update + delta = datetime.now(timezone.utc) - self.last_update last_update = "{} ago".format( self.get_delta_string(delta) ) @@ -114,10 +115,10 @@ def get_items(self): info[key] = value continue - datetime_value = datetime.datetime.strptime( + datetime_value = datetime.strptime( value, "%Y.%m.%d %H:%M:%S" ) - delta = datetime.datetime.now() - datetime_value + delta = datetime.now(timezone.utc) - datetime_value running_for = self.get_delta_string(delta) info["Started at"] = "{} [running: {}]".format(value, running_for) @@ -358,7 +359,7 @@ def server_activity(event): def trigger_info_get(): if ObjectFactory.last_trigger: - delta = datetime.datetime.now() - ObjectFactory.last_trigger + delta = datetime.now(timezone.utc) - ObjectFactory.last_trigger if delta.seconds() < 5: return diff --git a/src/quadpype/modules/ftrack/scripts/sub_event_storer.py b/src/quadpype/modules/ftrack/scripts/sub_event_storer.py index 1781950b6c..9c3cd5dfa6 100644 --- a/src/quadpype/modules/ftrack/scripts/sub_event_storer.py +++ b/src/quadpype/modules/ftrack/scripts/sub_event_storer.py @@ -1,10 +1,11 @@ import os import sys -import datetime import signal import socket import pymongo +from datetime import datetime, timezone + import ftrack_api from quadpype.client import QuadPypeMongoConnection @@ -23,7 +24,7 @@ ) log = Logger.get_logger("Event storer") -subprocess_started = datetime.datetime.now() +subprocess_started = datetime.now(timezone.utc) class SessionFactory: @@ -57,7 +58,7 @@ def launch(event): event_id = event["id"] event_data["pype_data"] = { - "stored": datetime.datetime.utcnow(), + "stored": datetime.now(timezone.utc), "is_processed": False } diff --git a/src/quadpype/modules/ftrack/scripts/sub_legacy_server.py b/src/quadpype/modules/ftrack/scripts/sub_legacy_server.py index 4f98497a75..8611f5549a 100644 --- a/src/quadpype/modules/ftrack/scripts/sub_legacy_server.py +++ b/src/quadpype/modules/ftrack/scripts/sub_legacy_server.py @@ -1,9 +1,10 @@ import sys import time -import datetime import signal import threading +from datetime import datetime, timezone + import ftrack_api from quadpype.lib import Logger from quadpype.modules import ModulesManager @@ -26,7 +27,7 @@ def stop(self): self.is_running = False def run(self): - start = datetime.datetime.now() + start = datetime.now(timezone.utc) self.is_running = True connected = False @@ -37,7 +38,7 @@ def run(self): if not self.session.event_hub.connected: if not connected: if ( - (datetime.datetime.now() - start).seconds > + (datetime.now(timezone.utc) - start).seconds > self.max_time_out ): log.error(( diff --git a/src/quadpype/modules/ftrack/tray/ftrack_tray.py b/src/quadpype/modules/ftrack/tray/ftrack_tray.py index 9a109e27c6..2b60c29f60 100644 --- a/src/quadpype/modules/ftrack/tray/ftrack_tray.py +++ b/src/quadpype/modules/ftrack/tray/ftrack_tray.py @@ -1,8 +1,9 @@ import os import time -import datetime import threading +from datetime import datetime, timezone + import ftrack_api from qtpy import QtCore, QtWidgets, QtGui @@ -136,7 +137,7 @@ def set_action_server(self): self.thread_socket_server.join() self.thread_socket_server = None - last_failed = datetime.datetime.now() + last_failed = datetime.now(timezone.utc) failed_count = 0 ftrack_accessible = False @@ -193,7 +194,7 @@ def set_action_server(self): failed_count += 1 elif (( - datetime.datetime.now() - last_failed + datetime.now(timezone.utc) - last_failed ).seconds > wait_time_after_max_fail): failed_count = 0 @@ -206,7 +207,7 @@ def set_action_server(self): self.bool_action_thread_running = False self.set_menu_visibility() - _last_failed = datetime.datetime.now() + _last_failed = datetime.now(timezone.utc) delta_time = (_last_failed - last_failed).seconds if delta_time < min_fail_seconds: failed_count += 1 diff --git a/src/quadpype/modules/job_queue/job_server/jobs.py b/src/quadpype/modules/job_queue/job_server/jobs.py index 0fc3c381d4..e739af9315 100644 --- a/src/quadpype/modules/job_queue/job_server/jobs.py +++ b/src/quadpype/modules/job_queue/job_server/jobs.py @@ -1,7 +1,8 @@ -import datetime import collections from uuid import uuid4 +from datetime import datetime, timezone + class Job: """Job related to specific host name. @@ -16,7 +17,7 @@ def __init__(self, host_name, data, job_id=None, created_time=None): job_id = str(uuid4()) self._id = job_id if created_time is None: - created_time = datetime.datetime.now() + created_time = datetime.now(timezone.utc) self._created_time = created_time self._started_time = None self._done_time = None @@ -36,7 +37,7 @@ def keep_in_memory(self): if self._done_time is None: return True - now = datetime.datetime.now() + now = datetime.now(timezone.utc) delta = now - self._done_time return delta.days < self.keep_in_memory_days @@ -82,12 +83,12 @@ def set_worker(self, worker): worker.set_current_job(self) def set_started(self): - self._started_time = datetime.datetime.now() + self._started_time = datetime.now(timezone.utc) self._started = True def set_done(self, success=True, message=None, data=None): self._done = True - self._done_time = datetime.datetime.now() + self._done_time = datetime.now(timezone.utc) self._errored = not success self._message = message self._result_data = data @@ -130,7 +131,7 @@ class JobQueue: old_jobs_check_minutes_interval = 30 def __init__(self): - self._last_old_jobs_check = datetime.datetime.now() + self._last_old_jobs_check = datetime.now(timezone.utc) self._jobs_by_id = {} self._job_queue_by_host_name = collections.defaultdict( collections.deque @@ -214,7 +215,7 @@ def create_job(self, host_name, job_data): def _remove_old_jobs(self): """Once in specific time look if should remove old finished jobs.""" - delta = datetime.datetime.now() - self._last_old_jobs_check + delta = datetime.now(timezone.utc) - self._last_old_jobs_check if delta.seconds < self.old_jobs_check_minutes_interval: return diff --git a/src/quadpype/modules/job_queue/job_workers/base_worker.py b/src/quadpype/modules/job_queue/job_workers/base_worker.py index 85506565f4..0f8fa292f7 100644 --- a/src/quadpype/modules/job_queue/job_workers/base_worker.py +++ b/src/quadpype/modules/job_queue/job_workers/base_worker.py @@ -1,8 +1,9 @@ import sys -import datetime import asyncio import traceback +from datetime import datetime, timezone + from aiohttp_json_rpc import JsonRpcClient @@ -94,9 +95,9 @@ async def main_loop(self, register_worker=True): self._is_running = True while not self._stopped: - start_time = datetime.datetime.now() + start_time = datetime.now(timezone.utc) await self._connection_loop(register_worker) - delta = datetime.datetime.now() - start_time + delta = datetime.now(timezone.utc) - start_time print("Connection loop took {}s".format(str(delta))) # Check if was stopped and stop while loop in that case if self._stopped: diff --git a/src/quadpype/modules/slack/plugins/publish/integrate_slack_api.py b/src/quadpype/modules/slack/plugins/publish/integrate_slack_api.py index 69786d3430..cf0c342ca6 100644 --- a/src/quadpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/src/quadpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -2,7 +2,7 @@ import re import pyblish.api import copy -from datetime import datetime +from datetime import datetime, timezone from abc import ABC, abstractmethod import time @@ -82,7 +82,7 @@ def process(self, instance): "msg_id": msg_id, "file_ids": file_ids, "project": project, - "created_dt": datetime.now() + "created_dt": datetime.now(timezone.utc) } mongo_client = QuadPypeMongoConnection.get_mongo_client() database_name = os.environ["QUADPYPE_DATABASE_NAME"] diff --git a/src/quadpype/modules/sync_server/sync_server_module.py b/src/quadpype/modules/sync_server/sync_server_module.py index 9020bab672..fd3eb0b983 100644 --- a/src/quadpype/modules/sync_server/sync_server_module.py +++ b/src/quadpype/modules/sync_server/sync_server_module.py @@ -1,10 +1,11 @@ import os import sys import time -from datetime import datetime import threading import copy import signal + +from datetime import datetime, timezone from collections import deque, defaultdict from bson.objectid import ObjectId @@ -303,7 +304,7 @@ def compute_resource_sync_sites(self, project_name): [ { 'name': '42abbc09-d62a-44a4-815c-a12cd679d2d7', - 'created_dt': datetime.datetime(2022, 3, 30, 12, 16, 9, 778637) + 'created_dt': datetime(2022, 3, 30, 12, 16, 9, 778637) }, {'name': 'studio'}, {'name': 'SFTP'} @@ -316,7 +317,7 @@ def create_metadata(name, created=True): """Create sync site metadata for site with `name`""" metadata = {"name": name} if created: - metadata["created_dt"] = datetime.now() + metadata["created_dt"] = datetime.now(timezone.utc) return metadata if ( @@ -528,7 +529,7 @@ def validate_project(self, project_name, site_name, reset_missing=False): repre_id)) created_dt = datetime.fromtimestamp( - os.path.getmtime(local_file_path)) + os.path.getmtime(local_file_path), tz=timezone.utc) elem = {"name": site_name, "created_dt": created_dt} self._add_site(project_name, repre, elem, @@ -1275,7 +1276,7 @@ def handle_alternate_site(self, project_name, representation, for alt_site in alternate_sites: elem = {"name": alt_site, - "created_dt": datetime.now(), + "created_dt": datetime.now(timezone.utc), "id": synced_file_id} self.log.debug("Adding alternate {} to {}".format( @@ -2308,7 +2309,7 @@ def _get_success_dict(self, new_file_id): (dictionary) """ val = {"files.$[f].sites.$[s].id": new_file_id, - "files.$[f].sites.$[s].created_dt": datetime.now()} + "files.$[f].sites.$[s].created_dt": datetime.now(timezone.utc)} return val def _get_error_dict(self, error="", tries="", progress=""): @@ -2321,7 +2322,7 @@ def _get_error_dict(self, error="", tries="", progress=""): Returns: (dictionary) """ - val = {"files.$[f].sites.$[s].last_failed_dt": datetime.now(), + val = {"files.$[f].sites.$[s].last_failed_dt": datetime.now(timezone.utc), "files.$[f].sites.$[s].error": error, "files.$[f].sites.$[s].tries": tries, "files.$[f].sites.$[s].progress": progress diff --git a/src/quadpype/modules/sync_server/tray/models.py b/src/quadpype/modules/sync_server/tray/models.py index b251ab8ff4..0f61fa0b77 100644 --- a/src/quadpype/modules/sync_server/tray/models.py +++ b/src/quadpype/modules/sync_server/tray/models.py @@ -1,8 +1,9 @@ import os + +from datetime import datetime, timezone + import attr from bson.objectid import ObjectId -import datetime - from qtpy import QtCore import qtawesome @@ -577,7 +578,7 @@ def add_page_records(self, local_site, remote_site, representations): remote_provider = lib.translate_provider_for_icon(self.sync_server, self.project, remote_site) - current_date = datetime.datetime.now() + current_date = datetime.now(timezone.utc) for repre in result.get("paginatedResults"): files = repre.get("files", []) if isinstance(files, dict): # aggregate returns dictionary @@ -659,7 +660,7 @@ def get_query(self, limit=0): limit = SyncRepresentationSummaryModel.PAGE_SIZE # replace null with value in the future for better sorting - dummy_max_date = datetime.datetime(2099, 1, 1) + dummy_max_date = datetime(2099, 1, 1, tzinfo=timezone.utc) aggr = [ {"$match": self.get_match_part()}, {'$unwind': '$files'}, @@ -1053,7 +1054,7 @@ def add_page_records(self, local_site, remote_site, representations): self.project, remote_site) - current_date = datetime.datetime.now() + current_date = datetime.now(timezone.utc) for repre in result.get("paginatedResults"): # log.info("!!! repre:: {}".format(repre)) files = repre.get("files", []) @@ -1115,7 +1116,7 @@ def get_query(self, limit=0): if limit == 0: limit = SyncRepresentationSummaryModel.PAGE_SIZE - dummy_max_date = datetime.datetime(2099, 1, 1) + dummy_max_date = datetime(2099, 1, 1, tzinfo=timezone.utc) aggr = [ {"$match": self.get_match_part()}, {"$unwind": "$files"}, diff --git a/src/quadpype/modules/update_zxp_extensions_action.py b/src/quadpype/modules/update_zxp_extensions_action.py deleted file mode 100644 index a5e11673fa..0000000000 --- a/src/quadpype/modules/update_zxp_extensions_action.py +++ /dev/null @@ -1,38 +0,0 @@ -import os - -from quadpype.modules import QuadPypeModule, ITrayAction -from quadpype.settings import get_global_settings -from quadpype.lib.version import get_package - -import igniter -from igniter.zxp_utils import get_zxp_extensions_to_update - - -class UpdateZXPExtensionsAction(QuadPypeModule, ITrayAction): - name = "update_zxp_extensions" - label = "Update ZXP Extensions" - submenu = "More Tools" - - def __init__(self, manager, settings): - super().__init__(manager, settings) - - def initialize(self, _modules_settings): - self.enabled = True - if os.getenv("QUADPYPE_IGNORE_ZXP_UPDATE"): - self.enabled = False - - def tray_init(self): - return - - def tray_start(self): - return - - def tray_exit(self): - return - - def on_action_trigger(self): - quadpype_version = get_package("quadpype").running_version - - global_settings = get_global_settings() - zxp_hosts_to_update = get_zxp_extensions_to_update(quadpype_version.path, global_settings, force=True) - igniter.open_zxp_update_window(quadpype_version.path, zxp_hosts_to_update) diff --git a/src/quadpype/plugins/publish/extract_otio_review.py b/src/quadpype/plugins/publish/extract_otio_review.py index d11fbfad5e..dd6a06c792 100644 --- a/src/quadpype/plugins/publish/extract_otio_review.py +++ b/src/quadpype/plugins/publish/extract_otio_review.py @@ -70,6 +70,10 @@ def process(self, instance): handle_end = instance.data["handleEnd"] otio_review_clips = instance.data["otioReviewClips"] + if otio_review_clips is None: + self.log.info(f"Instance `{instance}` has no otioReviewClips") + return + # add plugin wide attributes self.representation_files = list() self.used_frames = list() @@ -85,8 +89,7 @@ def process(self, instance): # skip instance if no reviewable data available if (not isinstance(otio_review_clips[0], otio.schema.Clip)) \ and (len(otio_review_clips) == 1): - self.log.warning( - "Instance `{}` has nothing to process".format(instance)) + self.log.warning(f"Instance `{instance}` has nothing to process") return else: self.staging_dir = self.staging_dir(instance) diff --git a/src/quadpype/plugins/publish/integrate.py b/src/quadpype/plugins/publish/integrate.py index f6230a3096..bbfd2b74e5 100644 --- a/src/quadpype/plugins/publish/integrate.py +++ b/src/quadpype/plugins/publish/integrate.py @@ -1,7 +1,8 @@ import os import logging import copy -import datetime + +from datetime import datetime, timezone import clique from bson.objectid import ObjectId @@ -328,7 +329,7 @@ def register(self, instance, file_transactions, filtered_repres): if sync_server_module is None: sites = [{ "name": "studio", - "created_dt": datetime.datetime.now() + "created_dt": datetime.now(timezone.utc) }] else: sites = sync_server_module.compute_resource_sync_sites( diff --git a/src/quadpype/settings/handlers.py b/src/quadpype/settings/handlers.py index fc4ff5c70b..43ed72fc3a 100644 --- a/src/quadpype/settings/handlers.py +++ b/src/quadpype/settings/handlers.py @@ -1,8 +1,9 @@ import os import copy import collections -import datetime import platform + +from datetime import datetime, timezone from abc import ABC, abstractmethod import quadpype.version @@ -69,7 +70,7 @@ def __init__( timestamp_obj = None if timestamp: - timestamp_obj = datetime.datetime.strptime( + timestamp_obj = datetime.strptime( timestamp, self.timestamp_format ) self.timestamp = timestamp @@ -91,7 +92,7 @@ def create_new( from quadpype.lib import get_user_workstation_info - now = datetime.datetime.now() + now = datetime.now(timezone.utc) workstation_info = get_user_workstation_info() return cls( @@ -804,7 +805,7 @@ def save_change_log(self, project_name, changes, settings_type): "workstation_name": host_info["workstation_name"], "host_ip": host_info["host_ip"], "system_name": host_info["system_name"], - "date_created": datetime.datetime.now(), + "date_created": datetime.now(timezone.utc), "project": project_name, "settings_type": settings_type, "changes": changes diff --git a/src/quadpype/tests/mongo_performance.py b/src/quadpype/tests/mongo_performance.py index 7e3516651c..89cf9563d4 100644 --- a/src/quadpype/tests/mongo_performance.py +++ b/src/quadpype/tests/mongo_performance.py @@ -1,7 +1,7 @@ import pymongo import bson import random -from datetime import datetime +from datetime import datetime, timezone import os @@ -267,7 +267,7 @@ def get_sites(self, number_of_sites=50): site = {'name': "local_{}".format(i)} # do not create null 'created_dt' field, Mongo doesnt like it if i == 0: - site['created_dt'] = datetime.now() + site['created_dt'] = datetime.now(timezone.utc) sites.append(site) diff --git a/src/quadpype/tools/loader/widgets.py b/src/quadpype/tools/loader/widgets.py index 884c3bd67c..ca58a891cc 100644 --- a/src/quadpype/tools/loader/widgets.py +++ b/src/quadpype/tools/loader/widgets.py @@ -1,10 +1,10 @@ import os import sys -import datetime import pprint import traceback import collections +from datetime import datetime from qtpy import QtWidgets, QtCore, QtGui from quadpype.client import ( @@ -716,8 +716,14 @@ def set_version(self, version_doc=None, version_id=None): # Define readable creation timestamp created = version_doc["data"]["time"] - created = datetime.datetime.strptime(created, "%Y%m%dT%H%M%SZ") - created = datetime.datetime.strftime(created, "%b %d %Y %H:%M") + try: + # Retro-compatibility, for published elements before version 4.0.13 + created = datetime.strptime(created, "%Y%m%dT%H%M%SZ") + except ValueError: + created = datetime.fromisoformat(created) + + created = created.astimezone() + created = datetime.strftime(created, "%b %d %Y %H:%M") comment = version_doc["data"].get("comment", None) or "No comment" @@ -747,7 +753,7 @@ def set_version(self, version_doc=None, version_id=None): "Comment
" "{comment}

" - "Created
" + "Created (in local timezone)
" "{created}

" "Source
" diff --git a/src/quadpype/tools/push_to_project/control_integrate.py b/src/quadpype/tools/push_to_project/control_integrate.py index c5ce4f49ae..759f774c08 100644 --- a/src/quadpype/tools/push_to_project/control_integrate.py +++ b/src/quadpype/tools/push_to_project/control_integrate.py @@ -3,10 +3,11 @@ import copy import socket import itertools -import datetime import sys import traceback +from datetime import datetime, timezone + from bson.objectid import ObjectId from quadpype.client import ( @@ -1114,7 +1115,7 @@ def _prepare_database_operations( if sync_server_module is None or not sync_server_module.enabled: sites = [{ "name": "studio", - "created_dt": datetime.datetime.now() + "created_dt": datetime.now(timezone.utc) }] else: sites = sync_server_module.compute_resource_sync_sites( diff --git a/src/quadpype/tools/settings/settings/base.py b/src/quadpype/tools/settings/settings/base.py index 35b18150c1..29f87a3ede 100644 --- a/src/quadpype/tools/settings/settings/base.py +++ b/src/quadpype/tools/settings/settings/base.py @@ -3,8 +3,8 @@ import json import traceback import functools -import datetime +from datetime import datetime, timezone from abc import abstractmethod from qtpy import QtWidgets, QtGui, QtCore @@ -64,7 +64,7 @@ def ask_for_save_filepath(cls, parent): @classmethod def extract_settings_to_json(cls, filepath, settings_data, project_name): - now = datetime.datetime.now() + now = datetime.now(timezone.utc) settings_data[SAVE_TIME_KEY] = now.strftime("%Y-%m-%d %H:%M:%S") if project_name != 0: settings_data[PROJECT_NAME_KEY] = project_name diff --git a/src/quadpype/tools/stdout_broker/app.py b/src/quadpype/tools/stdout_broker/app.py index 502f95ef9c..c513147f43 100644 --- a/src/quadpype/tools/stdout_broker/app.py +++ b/src/quadpype/tools/stdout_broker/app.py @@ -4,7 +4,7 @@ import collections import websocket import json -from datetime import datetime +from datetime import datetime, timezone from quadpype.lib import Logger from quadpype_modules.webserver.host_console_listener import MsgAction @@ -28,7 +28,7 @@ def __init__(self, host_name): self.original_stderr_write = None self.log_queue = collections.deque() - date_str = datetime.now().strftime("%d%m%Y%H%M%S") + date_str = datetime.now(timezone.utc).strftime("%d%m%Y%H%M%S") self.host_id = "{}_{}".format(self.host_name, date_str) self._std_available = False diff --git a/src/quadpype/tools/utils/delegates.py b/src/quadpype/tools/utils/delegates.py index 10167a3f60..ef302de614 100644 --- a/src/quadpype/tools/utils/delegates.py +++ b/src/quadpype/tools/utils/delegates.py @@ -1,5 +1,4 @@ -import time -from datetime import datetime +from datetime import datetime, timezone import logging import numbers @@ -219,7 +218,7 @@ def pretty_date(t, now=None, strftime="%b %d %Y %H:%M"): assert isinstance(t, datetime) if now is None: - now = datetime.now() + now = datetime.now(timezone.utc) assert isinstance(now, datetime) diff = now - t @@ -245,6 +244,8 @@ def pretty_date(t, now=None, strftime="%b %d %Y %H:%M"): hours = second_diff // 3600 return "{0}:{1:02d} hours ago".format(hours, minutes) + t = t.astimezone() + return t.strftime(strftime) @@ -268,23 +269,29 @@ def pretty_timestamp(t, now=None): if now is not None: try: - now = time.strptime(now, "%Y%m%dT%H%M%SZ") - now = datetime.fromtimestamp(time.mktime(now)) - except ValueError as e: - log.warning("Can't parse 'now' time format: {0} {1}".format(t, e)) - return None + # Retro-compatibility, for published elements before version 4.0.13 + now = datetime.strptime(now, "%Y%m%dT%H%M%SZ") + except ValueError: + try: + now = datetime.fromisoformat(now) + except ValueError as e: + log.warning("Can't parse 'now' time format: {0} {1}".format(t, e)) + return None if isinstance(t, float): - dt = datetime.fromtimestamp(t) + dt = datetime.fromtimestamp(t, tz=timezone.utc) else: # Parse the time format as if it is `str` result from - # `pyblish.lib.time()` which usually is stored in Avalon database. + # `pyblish.lib.time()` which usually is stored in QuadPype database. try: - t = time.strptime(t, "%Y%m%dT%H%M%SZ") - except ValueError as e: - log.warning("Can't parse time format: {0} {1}".format(t, e)) - return None - dt = datetime.fromtimestamp(time.mktime(t)) + # Retro-compatibility, for published elements before version 4.0.13 + dt = datetime.strptime(t, "%Y%m%dT%H%M%SZ") + except ValueError: + try: + dt = datetime.fromisoformat(t) + except ValueError as e: + log.warning("Can't parse time format: {0} {1}".format(t, e)) + return None # prettify return pretty_date(dt, now=now) diff --git a/src/quadpype/tools/workfiles/window.py b/src/quadpype/tools/workfiles/window.py index e04e043600..14ac859239 100644 --- a/src/quadpype/tools/workfiles/window.py +++ b/src/quadpype/tools/workfiles/window.py @@ -1,7 +1,9 @@ import os -import datetime import copy import platform + +from datetime import datetime + from qtpy import QtCore, QtWidgets, QtGui from quadpype.client import ( @@ -144,8 +146,8 @@ def set_context(self, asset_id, task_name, filepath, workfile_doc): # Append html string datetime_format = "%b %d %Y %H:%M:%S" - creation_time = datetime.datetime.fromtimestamp(filestat.st_ctime) - modification_time = datetime.datetime.fromtimestamp(filestat.st_mtime) + creation_time = datetime.fromtimestamp(filestat.st_ctime) + modification_time = datetime.fromtimestamp(filestat.st_mtime) lines = ( "Size:", size_value, diff --git a/src/start.py b/src/start.py index 998572d1a8..8c279d4a7c 100644 --- a/src/start.py +++ b/src/start.py @@ -184,12 +184,6 @@ def _print(msg: str, force=False): ssl_cert_file = certifi.where() os.environ["SSL_CERT_FILE"] = ssl_cert_file -if "--zxp-ignore-update" in sys.argv: - os.environ["QUADPYPE_IGNORE_ZXP_UPDATE"] = "1" - sys.argv.remove("--zxp-ignore-update") -elif os.getenv("QUADPYPE_IGNORE_ZXP_UPDATE") != "1": - os.environ.pop("QUADPYPE_IGNORE_ZXP_UPDATE", None) - if "--headless" in sys.argv: os.environ["QUADPYPE_HEADLESS_MODE"] = "1" sys.argv.remove("--headless") @@ -939,9 +933,8 @@ def boot(): running_version = package_manager["quadpype"].running_version running_version_fullpath = running_version.path.resolve() - if not os.getenv("QUADPYPE_IGNORE_ZXP_UPDATE"): - _print(">>> Check ZXP extensions ...") - _update_zxp_extensions(running_version_fullpath, global_settings) + _print(">>> Check ZXP extensions ...") + _update_zxp_extensions(running_version_fullpath, global_settings) # print info when not running scripts defined in 'silent commands' if all(arg not in silent_commands for arg in sys.argv):