X-Git-Url: http://users.mur.at/ms/git/gitweb/?p=OpenColorIO-Configs.git;a=blobdiff_plain;f=aces_1.0.0%2Fpython%2Faces_ocio%2Fprocess.py;h=db23fc37abc24b4b4d26524560102b65a5b10225;hp=766a5c81d034cbba46950813be8915a3e58b833d;hb=d815605e42c964ddb306e32506caaa077b3cf160;hpb=f709faf99244c03fda0402d21e04578c31af8232 diff --git a/aces_1.0.0/python/aces_ocio/process.py b/aces_1.0.0/python/aces_ocio/process.py index 766a5c8..db23fc3 100755 --- a/aces_1.0.0/python/aces_ocio/process.py +++ b/aces_1.0.0/python/aces_ocio/process.py @@ -1,36 +1,97 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -'''A process wrapper class that maintains the text output and execution status of a process -or a list of other process wrappers which carry such data.''' +""" +A process wrapper class that maintains the text output and execution status of +a process or a list of other process wrappers which carry such data. +""" import os import sys import traceback -def readText(textFile): - if( textFile != "" ): - fp = open(textFile, 'rb') - # Create a text/plain message - text = (fp.read()) - fp.close() +__author__ = 'ACES Developers' +__copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers' +__license__ = '' +__maintainer__ = 'ACES Developers' +__email__ = 'aces@oscars.org' +__status__ = 'Production' + +__all__ = ['read_text', + 'write_text', + 'Process', + 'ProcessList', + 'main'] + + +def read_text(text_file): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + if text_file != '': + with open(text_file, 'rb') as fp: + text = (fp.read()) return text -# readText - -def writeText(text, textFile): - if( textFile != "" ): - fp = open(textFile, 'wb') - # Create a text/plain message - fp.write(text) - fp.close() + + +def write_text(text, text_file): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + if text_file != '': + with open(text_file, 'wb') as fp: + fp.write(text) return text -# readText + class Process: - "A process with logged output" + """ + A process with logged output. + """ + + def __init__(self, + description=None, + cmd=None, + args=[], + cwd=None, + env=None, + batch_wrapper=False): + """ + Initialize the standard class variables. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ - def __init__(self, description=None, cmd=None, args=[], cwd=None, env=None, batchWrapper=False): - "Initialize the standard class variables" self.cmd = cmd if not description: self.description = cmd @@ -44,154 +105,259 @@ class Process: self.echo = True self.cwd = cwd self.env = env - self.batchWrapper = batchWrapper - self.processKeys = [] - # __init__ + self.batch_wrapper = batch_wrapper + self.process_keys = [] + + def get_elapsed_seconds(self): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ - def getElapsedSeconds(self): import math + if self.end and self.start: delta = (self.end - self.start) - formatted = "%s.%s" % (delta.days * 86400 + delta.seconds, int(math.floor(delta.microseconds/1e3))) + formatted = '%s.%s' % (delta.days * 86400 + delta.seconds, + int(math.floor(delta.microseconds / 1e3))) else: formatted = None return formatted - # getElapsedtime - - def writeKey(self, writeDict, key=None, value=None, startStop=None): - "Write a key, value pair in a supported format" - if key != None and (value != None or startStop != None): - indent = '\t'*writeDict['indentationLevel'] - if writeDict['format'] == 'xml': - if startStop == 'start': - writeDict['logHandle'].write( "%s<%s>\n" % (indent, key) ) - elif startStop == 'stop': - writeDict['logHandle'].write( "%s\n" % (indent, key) ) + + def write_key(self, write_dict, key=None, value=None, start_stop=None): + """ + Writes a key / value pair in a supported format. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + if key != None and (value != None or start_stop != None): + indent = '\t' * write_dict['indentationLevel'] + if write_dict['format'] == 'xml': + if start_stop == 'start': + write_dict['logHandle'].write('%s<%s>\n' % (indent, key)) + elif start_stop == 'stop': + write_dict['logHandle'].write('%s\n' % (indent, key)) else: - writeDict['logHandle'].write( "%s<%s>%s\n" % (indent, key, value, key) ) - else: # writeDict['format'] == 'txt': - writeDict['logHandle'].write( "%s%40s : %s\n" % (indent, key, value) ) + write_dict['logHandle'].write( + '%s<%s>%s\n' % (indent, key, value, key)) + else: + write_dict['logHandle'].write( + '%s%40s : %s\n' % (indent, key, value)) + + def write_log_header(self, write_dict): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ - def writeLogHeader(self, writeDict): import platform - # Retrieve operating environment information - user = None try: user = os.getlogin() except: try: - user = os.getenv("USERNAME") - if user == None: - user = os.getenv("USER") + user = os.getenv('USERNAME') + if user is None: + user = os.getenv('USER') except: - user = "unknown_user" - try: - (sysname, nodename, release, version, machine, processor) = platform.uname() - except: - (sysname, nodename, release, version, machine, processor) = ("unknown_sysname", "unknown_nodename", "unknown_release", "unknown_version", "unknown_machine", "unknown_processor") + user = 'unknown_user' try: - hostname = platform.node() + (sysname, nodename, release, version, machine, + processor) = platform.uname() except: - hostname = "unknown_hostname" - - self.writeKey(writeDict, 'process', None, 'start' ) - writeDict['indentationLevel'] += 1 - - self.writeKey(writeDict, 'description', self.description ) - self.writeKey(writeDict, 'cmd', self.cmd ) - if self.args: self.writeKey(writeDict, 'args', ' '.join(self.args) ) - self.writeKey(writeDict, 'start', self.start ) - self.writeKey(writeDict, 'end', self.end ) - self.writeKey(writeDict, 'elapsed', self.getElapsedSeconds() ) - - self.writeKey(writeDict, 'user', user ) - self.writeKey(writeDict, 'sysname', sysname ) - self.writeKey(writeDict, 'nodename', nodename ) - self.writeKey(writeDict, 'release', release ) - self.writeKey(writeDict, 'version', version ) - self.writeKey(writeDict, 'machine', machine ) - self.writeKey(writeDict, 'processor', processor ) - - if len(self.processKeys) > 0: - self.writeKey(writeDict, 'processKeys', None, 'start' ) - for pair in self.processKeys: + (sysname, nodename, release, version, machine, processor) = ( + 'unknown_sysname', 'unknown_nodename', 'unknown_release', + 'unknown_version', 'unknown_machine', 'unknown_processor') + + self.write_key(write_dict, 'process', None, 'start') + write_dict['indentationLevel'] += 1 + + self.write_key(write_dict, 'description', self.description) + self.write_key(write_dict, 'cmd', self.cmd) + if self.args: + self.write_key(write_dict, 'args', ' '.join(self.args)) + self.write_key(write_dict, 'start', self.start) + self.write_key(write_dict, 'end', self.end) + self.write_key(write_dict, 'elapsed', self.get_elapsed_seconds()) + + self.write_key(write_dict, 'user', user) + self.write_key(write_dict, 'sysname', sysname) + self.write_key(write_dict, 'nodename', nodename) + self.write_key(write_dict, 'release', release) + self.write_key(write_dict, 'version', version) + self.write_key(write_dict, 'machine', machine) + self.write_key(write_dict, 'processor', processor) + + if len(self.process_keys) > 0: + self.write_key(write_dict, 'processKeys', None, 'start') + for pair in self.process_keys: (key, value) = pair - writeDict['indentationLevel'] += 1 - self.writeKey(writeDict, key, value ) - writeDict['indentationLevel'] -= 1 - self.writeKey(writeDict, 'processKeys', None, 'stop' ) - - self.writeKey(writeDict, 'status', self.status ) - # writeLogHeader - - def writeLogFooter(self, writeDict): - writeDict['indentationLevel'] -= 1 - self.writeKey(writeDict, 'process', None, 'stop' ) - # writeLogFooter - - def writeLog(self, logHandle=sys.stdout, indentationLevel=0,format='xml'): - "Write logging information to the specified handle" - - writeDict = {} - writeDict['logHandle'] = logHandle - writeDict['indentationLevel'] = indentationLevel - writeDict['format'] = format - - if logHandle: - self.writeLogHeader(writeDict) - + write_dict['indentationLevel'] += 1 + self.write_key(write_dict, key, value) + write_dict['indentationLevel'] -= 1 + self.write_key(write_dict, 'processKeys', None, 'stop') + + self.write_key(write_dict, 'status', self.status) + + def write_log_footer(self, write_dict): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + write_dict['indentationLevel'] -= 1 + self.write_key(write_dict, 'process', None, 'stop') + + def write_log(self, + log_handle=sys.stdout, + indentation_level=0, + format='xml'): + """ + Writes logging information to the specified handle. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + write_dict = {} + write_dict['logHandle'] = log_handle + write_dict['indentationLevel'] = indentation_level + write_dict['format'] = format + + if log_handle: + self.write_log_header(write_dict) + if self.log: - self.writeKey(writeDict, 'output', None, 'start' ) + self.write_key(write_dict, 'output', None, 'start') if format == 'xml': - logHandle.write( "\n" ) - self.writeKey(writeDict, 'output', None, 'stop' ) + log_handle.write(']]>\n') + self.write_key(write_dict, 'output', None, 'stop') + + self.write_log_footer(write_dict) + + def write_log_to_disk(self, log_filename=None, format='xml', header=None): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. - self.writeLogFooter(writeDict) - # writeLog + Returns + ------- + type + Return value description. + """ - def writeLogToDisk(self, logFilename=None, format='xml', header=None): - if logFilename: + if log_filename: try: - # This also doesn't seem like the best structure... + # TODO: Review statements. # 3.1 try: - logHandle = open( logFilename, mode='wt', encoding="utf-8") + log_handle = ( + open(log_filename, mode='wt', encoding='utf-8')) # 2.6 except: - logHandle = open( logFilename, mode='wt') + log_handle = open(log_filename, mode='wt') except: - print( "Couldn't open log : %s" % logFilename ) - logHandle = None + print('Couldn\'t open log : %s' % log_filename) + log_handle = None - if logHandle: + if log_handle: if header: if format == 'xml': - logHandle.write( "\n" ) - self.writeLog(logHandle) - logHandle.close() - # writeLogToDisk - - def logLine(self, line): - "Add a line of text to the log" - self.log.append( line.rstrip() ) + log_handle.write(']]>\n') + self.write_log(log_handle) + log_handle.close() + + def log_line(self, line): + """ + Adds a line of text to the log. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + self.log.append(line.rstrip()) if self.echo: - print( "%s" % line.rstrip() ) - # logLine + print('%s' % line.rstrip()) def execute(self): - "Execute this process" - import re + """ + Executes the current process. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + import datetime import traceback - + try: import subprocess as sp except: @@ -201,96 +367,100 @@ class Process: cmdargs = [self.cmd] cmdargs.extend(self.args) - + if self.echo: if sp: - print( "\n%s : %s\n" % (self.__class__, sp.list2cmdline(cmdargs)) ) + print( + '\n%s : %s\n' % (self.__class__, sp.list2cmdline(cmdargs))) else: - print( "\n%s : %s\n" % (self.__class__, " ".join(cmdargs)) ) + print('\n%s : %s\n' % (self.__class__, ' '.join(cmdargs))) - # intialize a few variables that may or may not be set later process = None - tmpWrapper = None + tmp_wrapper = None stdout = None stdin = None parentenv = os.environ parentcwd = os.getcwd() try: - # Using subprocess + # Using *subprocess*. if sp: - if self.batchWrapper: - cmd = " ".join(cmdargs) - tmpWrapper = os.path.join(self.cwd, "process.bat") - writeText(cmd, tmpWrapper) - print( "%s : Running process through wrapper %s\n" % (self.__class__, tmpWrapper) ) - process = sp.Popen([tmpWrapper], stdout=sp.PIPE, stderr=sp.STDOUT, - cwd=self.cwd, env=self.env) + if self.batch_wrapper: + cmd = ' '.join(cmdargs) + tmp_wrapper = os.path.join(self.cwd, 'process.bat') + write_text(cmd, tmp_wrapper) + print('%s : Running process through wrapper %s\n' % ( + self.__class__, tmp_wrapper)) + process = sp.Popen([tmp_wrapper], stdout=sp.PIPE, + stderr=sp.STDOUT, + cwd=self.cwd, env=self.env) else: - process = sp.Popen(cmdargs, stdout=sp.PIPE, stderr=sp.STDOUT, - cwd=self.cwd, env=self.env) + process = sp.Popen(cmdargs, stdout=sp.PIPE, + stderr=sp.STDOUT, + cwd=self.cwd, env=self.env) - # using os.popen4 + # using *os.popen4*. else: if self.env: os.environ = self.env if self.cwd: - os.chdir( self.cwd ) - - stdin, stdout = os.popen4( cmdargs, 'r') + os.chdir(self.cwd) + + stdin, stdout = os.popen4(cmdargs, 'r') except: - print( "Couldn't execute command : %s" % cmdargs[0] ) + print('Couldn\'t execute command : %s' % cmdargs[0]) traceback.print_exc() - # Using subprocess + # Using *subprocess* if sp: if process != None: - #pid = process.pid - #log.logLine( "process id %s\n" % pid ) + # pid = process.pid + # log.logLine('process id %s\n' % pid) try: - # This is more proper python, and resolves some issues with a process ending before all - # of its output has been processed, but it also seems to stall when the read buffer - # is near or over it's limit. this happens relatively frequently with processes - # that generate lots of print statements. - # + # This is more proper python, and resolves some issues with + # a process ending before all of its output has been + # processed, but it also seems to stall when the read + # buffer is near or over its limit. This happens + # relatively frequently with processes that generate lots + # of print statements. for line in process.stdout: - self.logLine(line) - # - # So we go with the, um, uglier option below + self.log_line(line) + + # So we go with the, um, uglier option below. - # This is now used to ensure that the process has finished - line = "" - while line != None and process.poll() == None: + # This is now used to ensure that the process has finished. + line = '' + while line != None and process.poll() is None: try: line = process.stdout.readline() except: break # 3.1 try: - self.logLine( str(line, encoding="utf-8") ) + self.log_line(str(line, encoding='utf-8')) # 2.6 except: - self.logLine( line ) + self.log_line(line) except: - self.logLine( "Logging error : %s" % sys.exc_info()[0] ) + self.log_line('Logging error : %s' % sys.exc_info()[0]) self.status = process.returncode - - if self.batchWrapper and tmpWrapper: + + if self.batch_wrapper and tmp_wrapper: try: - os.remove(tmpWrapper) + os.remove(tmp_wrapper) except: - print( "Couldn't remove temp wrapper : %s" % tmpWrapper ) + print( + 'Couldn\'t remove temp wrapper : %s' % tmp_wrapper) traceback.print_exc() - # Using os.popen4 + # Using *os.popen4*. else: - exitCode = -1 + exit_code = -1 try: - #print( "reading stdout lines" ) - stdoutLines = stdout.readlines() - exitCode = stdout.close() + stdout_lines = stdout.readlines() + exit_code = stdout.close() stdout.close() stdin.close() @@ -298,54 +468,82 @@ class Process: if self.env: os.environ = parentenv if self.cwd: - os.chdir( parentcwd ) - - if len( stdoutLines ) > 0: - for line in stdoutLines: - self.logLine(line) - - if not exitCode: - exitCode = 0 + os.chdir(parentcwd) + + if len(stdout_lines) > 0: + for line in stdout_lines: + self.log_line(line) + + if not exit_code: + exit_code = 0 except: - self.logLine( "Logging error : %s" % sys.exc_info()[0] ) + self.log_line('Logging error : %s' % sys.exc_info()[0]) + + self.status = exit_code - self.status = exitCode - self.end = datetime.datetime.now() - #execute -# Process + class ProcessList(Process): - "A list of processes with logged output" + """ + A list of processes with logged output. + """ def __init__(self, description, blocking=True, cwd=None, env=None): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + Process.__init__(self, description, None, None, cwd, env) - "Initialize the standard class variables" + 'Initialize the standard class variables' self.processes = [] self.blocking = blocking - # __init__ - def generateReport(self, writeDict): - "Generate a log based on the success of the child processes" + def generate_report(self, write_dict): + """ + Generates a log based on the success of the child processes. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + if self.processes: _status = True - indent = '\t'*(writeDict['indentationLevel']+1) - + indent = '\t' * (write_dict['indentationLevel'] + 1) + self.log = [] - + for child in self.processes: if isinstance(child, ProcessList): - child.generateReport(writeDict) - - childResult = "" + child.generate_report(write_dict) + key = child.description value = child.status - if writeDict['format'] == 'xml': - childResult = ( "%s%s" % (indent, key, value) ) - else: # writeDict['format'] == 'txt': - childResult = ( "%s%40s : %s" % (indent, key, value) ) - self.log.append( childResult ) - + if write_dict['format'] == 'xml': + child_result = ( + '%s%s' % ( + indent, key, value)) + else: + child_result = ('%s%40s : %s' % (indent, key, value)) + self.log.append(child_result) + if child.status != 0: _status = False if not _status: @@ -353,56 +551,109 @@ class ProcessList(Process): else: self.status = 0 else: - self.log = ["No child processes available to generate a report"] + self.log = ['No child processes available to generate a report'] self.status = -1 - def writeLogHeader(self, writeDict): - self.writeKey(writeDict, 'processList', None, 'start' ) - writeDict['indentationLevel'] += 1 - - self.writeKey(writeDict, 'description', self.description ) - self.writeKey(writeDict, 'start', self.start ) - self.writeKey(writeDict, 'end', self.end ) - self.writeKey(writeDict, 'elapsed', self.getElapsedSeconds() ) - - self.generateReport(writeDict) - - self.writeKey(writeDict, 'status', self.status ) - # writeLogHeader - - def writeLogFooter(self, writeDict): - writeDict['indentationLevel'] -= 1 - self.writeKey(writeDict, 'processList', None, 'stop' ) - # writeLogFooter - - def writeLog(self, logHandle=sys.stdout, indentationLevel=0,format='xml'): - "Write logging information to the specified handle" - - writeDict = {} - writeDict['logHandle'] = logHandle - writeDict['indentationLevel'] = indentationLevel - writeDict['format'] = format - - if logHandle: - self.writeLogHeader(writeDict) - + def write_log_header(self, write_dict): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + self.write_key(write_dict, 'processList', None, 'start') + write_dict['indentationLevel'] += 1 + + self.write_key(write_dict, 'description', self.description) + self.write_key(write_dict, 'start', self.start) + self.write_key(write_dict, 'end', self.end) + self.write_key(write_dict, 'elapsed', self.get_elapsed_seconds()) + + self.generate_report(write_dict) + + self.write_key(write_dict, 'status', self.status) + + def write_log_footer(self, write_dict): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + write_dict['indentationLevel'] -= 1 + self.write_key(write_dict, 'processList', None, 'stop') + + def write_log(self, + log_handle=sys.stdout, + indentation_level=0, + format='xml'): + """ + Writes logging information to the specified handle. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + write_dict = {} + write_dict['logHandle'] = log_handle + write_dict['indentationLevel'] = indentation_level + write_dict['format'] = format + + if log_handle: + self.write_log_header(write_dict) + if self.log: - self.writeKey(writeDict, 'output', None, 'start' ) + self.write_key(write_dict, 'output', None, 'start') for line in self.log: - logHandle.write( '%s%s\n' % ("", line) ) - self.writeKey(writeDict, 'output', None, 'stop' ) + log_handle.write('%s%s\n' % ('', line)) + self.write_key(write_dict, 'output', None, 'stop') if self.processes: - self.writeKey(writeDict, 'processes', None, 'start' ) + self.write_key(write_dict, 'processes', None, 'start') for child in self.processes: - child.writeLog( logHandle, indentationLevel + 1, format ) - self.writeKey(writeDict, 'processes', None, 'stop' ) + child.write_log(log_handle, indentation_level + 1, format) + self.write_key(write_dict, 'processes', None, 'stop') - self.writeLogFooter(writeDict) - # writeLog + self.write_log_footer(write_dict) def execute(self): - "Execute this list of processes" + """ + Executes the list of processes. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + import datetime self.start = datetime.datetime.now() @@ -414,62 +665,71 @@ class ProcessList(Process): try: child.execute() except: - print( "%s : caught exception in child class %s" % (self.__class__, child.__class__) ) + print('%s : caught exception in child class %s' % ( + self.__class__, child.__class__)) traceback.print_exc() child.status = -1 if self.blocking and child.status != 0: - print( "%s : child class %s finished with an error" % (self.__class__, child.__class__) ) + print('%s : child class %s finished with an error' % ( + self.__class__, child.__class__)) self.status = -1 break self.end = datetime.datetime.now() - # execute -# ProcessList + def main(): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + import optparse p = optparse.OptionParser(description='A process logging script', - prog='process', - version='process 0.1', - usage='%prog [options] [options for the logged process]') + prog='process', + version='process 0.1', + usage=('%prog [options] ' + '[options for the logged process]')) p.add_option('--cmd', '-c', default=None) p.add_option('--log', '-l', default=None) options, arguments = p.parse_args() - # - # Get options - # cmd = options.cmd - logFilename = options.log + log_filename = options.log try: - argsStart = sys.argv.index('--') + 1 - args = sys.argv[argsStart:] + args_start = sys.argv.index('--') + 1 + args = sys.argv[args_start:] except: - argsStart = len(sys.argv)+1 + args_start = len(sys.argv) + 1 args = [] - if cmd == None: - print( "process: No command specified" ) - - # - # Test regular logging - # - process = Process(description="a process",cmd=cmd, args=args) - - # - # Test report generation and writing a log - # - processList = ProcessList("a process list") - processList.processes.append( process ) - processList.echo = True - processList.execute() - - processList.writeLogToDisk(logFilename) -# main + if cmd is None: + print('process: No command specified') + + # Testing regular logging. + process = Process(description='a process', cmd=cmd, args=args) + + # Testing report generation and writing a log. + process_list = ProcessList('a process list') + process_list.processes.append(process) + process_list.echo = True + process_list.execute() + + process_list.write_log_to_disk(log_filename) + if __name__ == '__main__': main()