mirror of
https://github.com/blw1138/Zordon.git
synced 2025-12-17 16:58:12 +00:00
138 lines
4.7 KiB
Python
138 lines
4.7 KiB
Python
import glob
|
|
import hashlib
|
|
import json
|
|
import logging
|
|
import os
|
|
import threading
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from .render_workers.render_worker import RenderStatus, RenderWorkerFactory
|
|
|
|
logger = logging.getLogger()
|
|
|
|
|
|
class RenderJob:
|
|
|
|
# Get file hash on bg thread
|
|
def __get_file_hash(self):
|
|
if os.path.exists(self.worker.input_path):
|
|
self.file_hash = hashlib.md5(open(self.worker.input_path, 'rb').read()).hexdigest()
|
|
|
|
def __init__(self, renderer, input_path, output_path, args, priority=2, owner=None, client=None, notify=None,
|
|
custom_id=None, name=None):
|
|
self.id = custom_id or self.generate_id()
|
|
self.owner = owner
|
|
self.priority = priority
|
|
self.client = client
|
|
self.notify = notify
|
|
self.date_created = datetime.now()
|
|
self.scheduled_start = None
|
|
self.renderer = renderer
|
|
self.name = name or os.path.basename(input_path) + '_' + self.date_created.strftime("%Y.%m.%d_%H.%M.%S")
|
|
|
|
self.worker = RenderWorkerFactory.create_worker(renderer, input_path, output_path, args)
|
|
self.worker.log_path = os.path.join(os.path.dirname(input_path), self.name + '.log')
|
|
|
|
self.file_hash = None
|
|
threading.Thread(target=self.__get_file_hash).start() # get file hash on bg thread
|
|
|
|
def render_status(self):
|
|
if self.scheduled_start and self.worker.status == RenderStatus.NOT_STARTED:
|
|
return RenderStatus.SCHEDULED
|
|
else:
|
|
return self.worker.status
|
|
|
|
def file_hash(self):
|
|
if os.path.exists(self.worker.input_path):
|
|
return hashlib.md5(open(self.worker.input_path, 'rb').read()).hexdigest()
|
|
return None
|
|
|
|
def json(self):
|
|
"""Converts RenderJob into JSON-friendly dict"""
|
|
job_dict = None
|
|
try:
|
|
job_dict = self.__dict__.copy()
|
|
job_dict['status'] = self.render_status().value
|
|
job_dict['time_elapsed'] = self.time_elapsed() if type(self.time_elapsed) != str else self.time_elapsed
|
|
job_dict['file_hash'] = self.file_hash
|
|
job_dict['percent_complete'] = self.percent_complete()
|
|
job_dict['file_list'] = self.file_list()
|
|
job_dict['worker'] = self.worker.__dict__.copy()
|
|
job_dict['worker']['status'] = job_dict['status']
|
|
|
|
# remove unwanted keys from dict
|
|
keys_to_remove = ['thread', 'process']
|
|
for key in job_dict['worker'].keys():
|
|
if key.startswith('_'):
|
|
keys_to_remove.append(key)
|
|
for key in keys_to_remove:
|
|
job_dict['worker'].pop(key, None)
|
|
|
|
# convert to json and back to auto-convert dates to iso format
|
|
def date_serializer(o):
|
|
if isinstance(o, datetime):
|
|
return o.isoformat()
|
|
json_convert = json.dumps(job_dict, default=date_serializer)
|
|
job_dict = json.loads(json_convert)
|
|
except Exception as e:
|
|
logger.exception(e)
|
|
logger.error("Error converting to JSON: {}".format(e))
|
|
return job_dict
|
|
|
|
def start(self):
|
|
self.worker.start()
|
|
|
|
def stop(self):
|
|
self.worker.stop()
|
|
|
|
def time_elapsed(self):
|
|
|
|
from string import Template
|
|
|
|
class DeltaTemplate(Template):
|
|
delimiter = "%"
|
|
|
|
def strfdelta(tdelta, fmt='%H:%M:%S'):
|
|
d = {"D": tdelta.days}
|
|
hours, rem = divmod(tdelta.seconds, 3600)
|
|
minutes, seconds = divmod(rem, 60)
|
|
d["H"] = '{:02d}'.format(hours)
|
|
d["M"] = '{:02d}'.format(minutes)
|
|
d["S"] = '{:02d}'.format(seconds)
|
|
t = DeltaTemplate(fmt)
|
|
return t.substitute(**d)
|
|
|
|
# calculate elapsed time
|
|
elapsed_time = None
|
|
start_time = self.worker.start_time
|
|
end_time = self.worker.end_time
|
|
|
|
if start_time:
|
|
if end_time:
|
|
elapsed_time = end_time - start_time
|
|
elif self.render_status() == RenderStatus.RUNNING:
|
|
elapsed_time = datetime.now() - start_time
|
|
|
|
elapsed_time_string = strfdelta(elapsed_time) if elapsed_time else "Unknown"
|
|
return elapsed_time_string
|
|
|
|
def frame_count(self):
|
|
return self.worker.total_frames
|
|
|
|
def work_path(self):
|
|
return os.path.dirname(self.worker.output_path)
|
|
|
|
def file_list(self):
|
|
job_dir = os.path.dirname(self.worker.output_path)
|
|
return glob.glob(os.path.join(job_dir, '*'))
|
|
|
|
def log_path(self):
|
|
return self.worker.log_path
|
|
|
|
def percent_complete(self):
|
|
return self.worker.percent_complete()
|
|
|
|
@classmethod
|
|
def generate_id(cls):
|
|
return str(uuid.uuid4()).split('-')[0] |