Source code for transmogrifier

#!/usr/bin/python

################################
##
##  Transmogrifier
##  A Final Cut Server import/export tool 
##
##  Written by: Beau Hunter beau@318.com
##  318 Inc 05/2009
##
##  See Introduction.pdf for information. This tool is intended to help
##  You get the most out of Final Cut Server, use at your own risk.
## 
##  It's amazing what they do with corrugated cardboard these days...
##
#############################################################


import sys, getopt, re, os, os.path, string, types, datetime, time
import fcsxml
#from brightcove import BrightCoveObject
#from youtube import YoutubeObject
#from thePlatform import thePlatformObject
#from shakeblender import ShakeBlenderObject
#from pcpblender import PCPBlenderObject
#from filemaker import FileMakerObject
#from sftp import sftpObject

from transmogrifierTarget import *
from ConfigParser import *

## init our vars
version = ".95beta"
build = "2011032802"
validActions = ['uploadMovies','uploadImages'] ## todo: determine these from our validTarget objects
validModules = []

## Change this to 1.0 if you aren't using 1.5 todo: check this dynamically
fcsMajorVersion = "1.5"

global debug
debug = False
forceDebug = True


######################### START FUNCTIONS ###############################

[docs]def helpMessage(): '''This function outputs transmogrifier usage syntax and help.''' print '''Usage: transmogrifier.py [options] [target] transmogrifier.py [-f configfile] [-d supportdir] [-a action] [-t mediatitle] Working with assets: transmogrifier.py --setField="Keywords" --value="MyAsset" -t MyAsset transmogrifier.py --setField="Keywords" --value="MyAsset" -i /fcsxmlinfile.xml transmogrifier.py --appendField="Status" --value="Update!" -i /fcsxmlinfile.xml transmogrifier.py --getAssetID --assetPath="/FCS/Media/myfile.mpg" transmogrifier.py --getEntityPath --assetID=1 transmogrifier.py --getThumbnailPath --assetID=1 transmogrifier.py --getProxyPath --assetID=1 transmogrifier.py --getPosterFramePath --assetID=1 transmogrifier.py --archive --assetID=1 transmogrifier.py --restore --assetID=1 transmogrifier.py --analyze --assetID=1 Working with productions: transmogrifier.py --setField="Owner" --value="Calvin" --assetsWithProductionID=1 transmogrifier.py --restore --productionID=1 Working with devices: transmogrifier.py --getDeviceName --deviceID=1 transmogrifier.py --getDeviceName --devicePath="/FCS/Media" transmogrifier.py --getDevicePath --deviceName="Media" transmogrifier.py --getDevicePath --deviceID=1 transmogrifier.py --getDeviceID --deviceName="Media" transmogrifier.py --getDeviceID --devicePath="/FCS/Media" Working with Modules: transmogrifier.py --module=BrightCove -t MyAsset [-a action] transmogrifier.py --module=BrightCove -a preflightCheck|upload -t MyAsset transmogrifier.py -a createSupportFolders [-m BrightCove] [-d supportdir] transmogrifier.py --module=BrightCove -a listFCSFields Options: -h, --help Displays this help message -v, --version Display version number -f configfilepath Use specified config file -d supportdir Path to support folder --xmlout= Specify a FCS XML file to write out. -m,--module=MODULE Delivery Target: 'BrightCove', 'YouTube',etc.. -a action Perform the requested action. --fcsvr_client Utilise fcsvr_client for FCS I/O operations This defaults to yes by default on certain operations --nofcsvr_client Under no circumstances utilize fcsvr_client for operations --getField=FIELD Method to retrieve the value of FIELD --getDBField=FIELD Method to retriev the value of FIELD using the Final Cut Server database field name. --setField=FIELD Method to specify FIELD to set with --value --appendField=FIELD Append the specified field FIELD with --value --value=value Data to append to set or import to --field --withtimestamp Prepends a time stamp to STRING --notimestamp Omits timestamp, if specified in config file --getAssetID Outputs the assetID for specified target asset --getAssetPath Outputs the asset's filesystem path --getEntityPath Outputs the FCS address for specified target asset --getEntityMetadataSet Outputs the metadata set associated with entity --getProxyPath Outputs the asset's proxy path --getEditProxyPath Outputs the asset's edit proxy path --getThumbnailPath Outputs the asset's thumbnail path --getPosterFramePath Outputs the asset's posterframe path --getDeviceName Outputs the deviceName for specified target --getDevicePath Outputs the device path for specified target --getDeviceID Outputs the device id for the specified target --getProductionTitle Outputs the production name of the specified target --getProductionID Outputs the production id of the specified target --addToProduction Adds the specified asset to the specified production --archive Archive the specified target --restore Restore the specified target --filterMDSet=mdset Filters objects to only those with the provided mdset (experimental) Targets: -t title,--title= Title of the XML file to read in, useful when using WriteXML response in FCS. Utilizes paths set in transmogrifier.conf --xmlin="/myfile.xml" Specify a FCS XML file to read in. Overwrites -t --assetID=1 Asset with ID 1 --assetPath="/myfile" Asset residing at "/myfile" --assetTitle="title" Asset with title "title" --productionID=1 Production with ID 1 --productionTitle='title' Production with title 'title' --productionTitleLike='title' Production with title matching substring 'title' --assetsFromProductionID=1 All assets from the specified production. --assetsFromProjectID= All assets linked from the provided FCP project file --deviceID=1 Device with ID 1 --deviceName="Media" Device with name "Media" Return Codes: 0 Clean Execution 1 Syntax Error 2 Syntax Error: parameter missing 5 Ambiguous/Conflicting Target 6 Invalid Action 7 fcsvr_client unavailable 8 Error reading from source (bad XML, fcsvr_client error) 9 Target(s) is(are) offline '''
[docs]def printVersionInfo(): '''Prints out version info''' print ("\nFCS transmogrifier\n\tVersion: %s Build: %s\n" "\tFramework Version: %s Build: %s\n\n" "Copyright (C) 2011 Beau Hunter, 318 Inc.\n" % (version,build, fcsxml.version, fcsxml.build))
[docs]def createSupportFolders(basePath, modules): '''Creates Support folder path utilized by various upload services, iterates through modules defined in list 'validFormets' ''' if not os.path.isdir(os.path.dirname(basePath)): print "Could not create folder structure, invalid path: '%s'" % basePath return False if not os.path.exists(basePath): print "Creating support folder: '%s'" % basePath os.mkdir(basePath) else: print "Using support folder: '%s'" % basePath if not os.path.isdir(basePath): print "Non-directory object exists at path: '%s', exiting!" % basePath return False ## generate our global Final Cut Server XML in folder fcsXMLDir = os.path.join(basePath,"fcsvr_xmlin") fcsXMLOutDir = os.path.join(basePath,"fcsvr_xmlout") if not os.path.isdir(fcsXMLDir): print "Creating fcsvr_xmlin directory." os.mkdir(fcsXMLDir) if not os.path.isdir(fcsXMLOutDir): print "Creating fcsvr_xmlout directory." os.mkdir(fcsXMLOutDir) ## test to see if we're passed a string, if so, convert it to a list if type(modules) == type("string"): modules = [modules] ## Iterate through our module objects and run the createSupportFolders method for module in modules: try: print "Creating folder structure for module: '%s'" % module theObject = eval("%sObject()" % module) theObject.debug = debug supportPath = os.path.join(basePath,module) supportPath = os.path.join(basePath,module) if not theObject.createSupportFolders(supportPath): print "Could Not create some or all support folders for module: '%s'" % module except: print "Problem creating module: '%sObject' may not be a valid class" % module print ""
[docs]def validActions(modules=validModules): '''Returns a list of all valid actions, based on provided modules.''' ## init our return var validActions = [] ## add our transmogrifier default actions. try: validActions = TransmogrifierTargetObject.validActions except: pass ## Iterate through our loaded modules and aggregate their actions. for module in modules: #print "Testing module: %s" % module try: theClass = eval('%sObject()' % module) except: print 'Could not resolve class for module: %s' % module try: ##print " - module actions: %s" % ', '.join(theClass.validActions) validActions.extend(theClass.validActions) except: print 'Could not resolve actions for module: %s' % module ##print "DEBUG: resolved actions: %s" % validActions return validActions ######################### END FUNCTIONS ################################# ######################### MAIN SCRIPT START #############################
[docs]def main(): '''Our main function, filters passed arguments and loads the appropriate object''' ## Init vars basePath = "" fileTitle = "" configFile = "" module = "" action = "" xmlinPath = "" newString = "" fcsvr_client = True ## Disabled by --nofcsvr_client fcsvr_client_all = False ## Set by --fcsvr_client useTimeStamp=False keepFiles = False expectsValue = False ## Used by our loop, when true, the next opt should be a --value fields = {} ## Fields as specified by our passed parameters targets = {} ## Targets as specified by our passed parameters filters = {} ## Target filters. useSecondTarget = False ## Whether our command has a second target. actions = [] ## Our actions exitCode = 0 ## Our Exit code global debug ## Get our flags try: optlist, list = getopt.getopt(sys.argv[1:],':hva:f:m:t:d::',["archive-type=", "action=","setField=","getField=","getDBField=","setBoolField=","title=", "action=","module=","appendField=","value=","xmlin","withtimestamp", "notimestamp","fcsvr_client","nofcsvr_client","help","version", "getAssetID","getAssetPath","getEntityPath","getEntityMetadataSet","getFilePath", "getProxyPath","getEditProxyPath","getPosterFramePath","getThumbnailPath", "getAssetTitle","getDeviceName","getDevicePath","getDeviceID","debug", "addToProduction","getProductionTitle","getProductionID","assetID=", "assetTitle=","assetPath=","assetsFromProductionID=","assetsFromProjectID=", "deviceID=","deviceName=","devicePath=","productionID=","productionTitle=", "productionTitleLike=","createProductionWithTitle=","filterMDSet=","archive","restore","analyze"]) except getopt.GetoptError: print "Syntax Error!" helpMessage() return 1 ## If no options are passed, output help if len(optlist) == 0: printVersionInfo() helpMessage() return 1 #### PROCESS OUR PASSED ARGUMENTS #### for opt in optlist: if expectsValue: if opt[0] == '--value': newValue = opt[1].replace('\\n','\n').replace('\\t','\t') myField = fields[fieldName] myField["value"] = newValue expectsValue = False continue else: print "Syntax Error! --field or --appendField must be followed by --value=" helpMessage() return 2 else: if opt[0] == '--value': print "Syntax Error! --value must follow --field or --appendField!" helpMessage() return 2 if opt[0] == '-h' or opt[0] == "--help": helpMessage() return 0 elif opt[0] == '-v' or opt[0] == "--version": printVersionInfo() return 0 elif opt[0] == '-d': basePath = opt[1] elif opt[0] == '-f': configFile = opt[1] elif opt[0] == '--filterMDSet': filters['mdSet'] = opt[1] elif opt[0] == "--fcsvr_client": fcsvr_client = True fcsvr_client_all = True elif opt[0] == "--nofcsvr_client": fcsvr_client = False fcsvr_client_all = False elif opt[0] == '-m' or opt[0] == "--module": module = opt[1] ## Read in our possible actions elif opt[0] == "--debug": debug = True forceDebug = True elif opt[0] == "--appendField": fieldName = opt[1] myaction = {"action":"appendField","fieldName":fieldName,"value":"","timestamp":useTimeStamp,"targets":["asset","assets","project"],"sources":["fcsvr_client","fcsxml"]} fields[fieldName] = myaction action="appendField" if not fcsvr_client and not fcsvr_client_all: module="TransmogrifierTarget" actions.append(myaction) expectsValue = True elif opt[0] == "--getField": fieldName = opt[1] myaction = {"action":"getField","fieldName":fieldName,"value":"","targets":["asset","assets","project"],"sources":["fcsvr_client","fcsxml"]} fields[fieldName] = myaction actions.append(myaction) fields[fieldName] = myaction action="getField" if not fcsvr_client: module="TransmogrifierTarget" elif opt[0] == "--getDBField": fieldName = opt[1] myaction = {"action":"getDBField","fieldName":fieldName,"value":"","targets":["asset","assets","project"],"sources":["fcsvr_client"]} fields[fieldName] = myaction actions.append(myaction) fields[fieldName] = myaction action="getField" elif opt[0] == "--setField": fieldName = opt[1] myaction = {"action":"setField","fieldName":fieldName,"value":"","timestamp":useTimeStamp,"targets":["asset","assets","project"],"sources":["fcsvr_client","fcsxml"]} fields[fieldName] = myaction actions.append(myaction) fields[fieldName] = myaction action="setField" if not fcsvr_client: module="TransmogrifierTarget" expectsValue = True elif opt[0] == "--setBoolField": fieldName = opt[1] myaction = {"action":"setBoolField","fieldName":fieldName,"value":"","timestamp":useTimeStamp,"targets":["asset","assets","project"],"sources":["fcsvr_client","fcsxml"]} fields[fieldName] = myaction actions.append(myaction) fields[fieldName] = myaction action="setField" if not fcsvr_client: module="TransmogrifierTarget" expectsValue = True elif opt[0] == "--archive": myaction = {"action":"archive","targets":["asset","assets","project"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--restore": myaction = {"action":"restore","targets":["asset","assets","project"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--analyze": myaction = {"action":"analyze","targets":["asset","assets","project"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getAssetTitle": myaction = {"action":"getAssetTitle","targets":["asset"],"sources":["fcsvr_client","fcsxml"]} action="internal" actions.append(myaction) elif opt[0] == "--getAssetPath": myaction = {"action":"getAssetPath","targets":["asset","assets"],"sources":["fcsvr_client","fcsxml"]} action="internal" actions.append(myaction) elif opt[0] == "--getAssetID": myaction = {"action":"getAssetID","targets":["asset","assets"],"sources":["fcsvr_client","fcsxml"]} action="internal" actions.append(myaction) elif opt[0] == "--getEntityPath": myaction = {"action":"getEntityPath","targets":["device","asset","assets"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getEntityMetadataSet": myaction = {"action":"getEntityMetadataSet","targets":["device","asset"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getFilePath": myaction = {"action":"getFilePath","targets":["asset","assets","device"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getProxyPath": myaction = {"action":"getProxyPath","targets":["asset"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getEditProxyPath": myaction = {"action":"getEditProxyPath","targets":["asset"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getPosterFramePath": myaction = {"action":"getPosterFramePath","targets":["asset"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getThumbnailPath": myaction = {"action":"getThumbnailPath","targets":["asset"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getProductionID": myaction = {"action":"getProductionID","targets":["project"],"sources":["fcsvr_client","fcsxml"]} action="internal" actions.append(myaction) elif opt[0] == "--getProductionTitle": myaction = {"action":"getProductionTitle","targets":["project"],"sources":["fcsvr_client","fcsxml"]} action="internal" actions.append(myaction) elif opt[0] == "--addToProduction": ##print "DEBUG: hit --addToProduction" myaction = {"action":"addToProduction","targets":["asset","project"],"target2":["project"],"sources":["fcsvr_client"]} action = "addToProduction" useSecondTarget = True actions.append(myaction) elif opt[0] == "--getDeviceID": myaction = {"action":"getDeviceID","targets":["device","asset"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) elif opt[0] == "--getDeviceName": myaction = {"action":"getDeviceName","targets":["device"],"sources":["fcsvr_client","fcsxml"]} action="internal" actions.append(myaction) elif opt[0] == "--getDevicePath": myaction = {"action":"getDevicePath","targets":["device"],"sources":["fcsvr_client"]} action="internal" actions.append(myaction) ## Read in our possible target elif opt[0] == '-t' or opt[0] == "--title": mytarget = {"target":"xmltitle","type":"asset","value":opt[1],"sources":["fcsxml"]} if "asset" in targets: print "Error! Specified conflicting targets: --title and --%s!!" % targets["asset"]["target"] helpMessage() return 5 targets["asset"] = mytarget fileTitle = opt[1] elif opt[0] == '-i' or opt[0] == "--xmlin": mytarget = {"target":"xmlin","type":"asset","value":opt[1],"sources":["fcsxml"]} if "asset" in targets: print "Error! Specified conflicting targets: --xmlin and --%s!!" % targets["asset"]["target"] helpMessage() return 5 targets["asset"] = mytarget xmlinPath == 'opt[1]' elif opt[0] == "--assetID": mytarget = {"target":"assetID","value":opt[1],"type":"asset","sources":["fcsvr_client","fcsxml","stdin"]} if "asset" in targets and not useSecondTarget: print "Error! Specified conflicting targets: --assetID and --%s!!" % targets["asset"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--assetTitle": mytarget = {"target":"assetTitle","value":opt[1],"type":"asset","sources":["fcsvr_client","stdin"]} if "asset" in targets and not useSecondTarget: print "Error! Specified conflicting targets: --assetTitle and --%s!!" % targets["asset"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--assetsFromProductionID": mytarget = {"target":"assetsFromProductionID","value":opt[1],"type":"assets","sources":["fcsvr_client","fcsxml","stdin"]} if "asset" in targets and not secondTarget: print "Error! Specified conflicting targets: --assetsFromProductionID and --%s!!" % targets["asset"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--assetsFromProjectID": mytarget = {"target":"assetsFromProjectID","value":opt[1],"type":"assets","sources":["fcsvr_client","stdin"]} if "asset" in targets and not secondTarget: print "Error! Specified conflicting targets: --assetsFromProjectID and --%s!!" % targets["asset"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--entityPath": entityPath = opt[1] mytarget = {"target":"entityPath","value":entityPath,"type":"asset","sources":["fcsvr_client"]} entityType = entityPath.split("/")[1] if entityType in targets and not secondTarget: print "Error! Specified conflicting targets: --assetPath and --%s!!" % targets["asset"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets[entityType] = mytarget elif opt[0] == "--assetPath": mytarget = {"target":"assetPath","value":opt[1],"type":"asset","sources":["fcsvr_client"]} if "asset" in targets and not useSecondTarget: print "Error! Specified conflicting targets: --assetPath and --%s!!" % targets["asset"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--productionID": mytarget = {"target":"productionID","value":opt[1],"type":"project","sources":["fcsvr_client",]} if "project" in targets and not useSecondTarget: print "Error! Specified conflicting targets: --productionID and --%s!!" % targets["project"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--productionTitle": mytarget = {"target":"productionTitle","value":opt[1],"type":"project","sources":["fcsvr_client",]} if "project" in targets and not useSecondTarget: print "Error! Specified conflicting targets: --productionID and --%s!!" % targets["project"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--productionTitleLike": mytarget = {"target":"productionTitleLike","value":opt[1],"type":"project","sources":["fcsvr_client",]} if "project" in targets and not useSecondTarget: print "Error! Specified conflicting targets: --productionID and --%s!!" % targets["project"]["target"] helpMessage() return 5 elif useSecondTarget and 'secondTarget' in targets: print "Error! You have already specified a second target: --%s!!" % secondTarget["target"] helpMessage() return 5 elif useSecondTarget and len(targets) > 0: targets['secondTarget'] = mytarget else: targets["asset"] = mytarget elif opt[0] == "--createProductionWithTitle": mytarget = {"target":"createProductionWithTitle","value":opt[1],"type":"project","sources":["fcsvr_client",]} myaction = {"action":"createProductionWithTitle","targets":["project"],"sources":["fcsvr_client"]} if "project" in targets: print "Error! Specified conflicting targets: --productionID and --%s!!" % targets["project"]["target"] helpMessage() return 5 else: targets["project"] = mytarget actions.append(myaction) elif opt[0] == "--deviceID": mytarget = {"target":"deviceID","value":opt[1],"type":"device","sources":["fcsvr_client"]} if "device" in targets: print "Error! Specified conflicting targets: --deviceID and --%s!!" % targets["device"]["target"] helpMessage() return 5 targets["device"] = mytarget elif opt[0] == "--deviceName": mytarget = {"target":"deviceName","value":opt[1],"type":"device","sources":["fcsvr_client","fcsxml"]} if "device" in targets: print "Error! Specified conflicting targets: --deviceName and --%s!!" % targets["device"]["target"] helpMessage() return 5 targets["device"] = mytarget elif opt[0] == "--devicePath": mytarget = {"target":"devicePath","value":opt[1],"type":"device","sources":["fcsvr_client"]} if "device" in targets: print "Error! Specified conflicting targets: --devicePath and --%s!!" % targets["device"]["target"] helpMessage() return 5 targets["device"] = mytarget elif opt[0] == '--withtimestamp': ## If we have fields set, apply the timestamp value to only the last ## specified field. If no fields are specified, we enable it globally if len(fields) > 0 and fieldName in fields: myField = fields[fieldName] myField["timestamp"] = True else: useTimeStamp = True elif opt[0] == '--notimestamp': ## If we have fields set, apply the timestamp value to only the last ## specified field. If no fields are specified, we disable it globally if len(fields) > 0 and fieldName in fields: myField = fields[fieldName] myField["timestamp"] = False else: useTimeStamp = False elif opt[0] == '-a' or opt[0] == '--action': action = opt[1] ## If no config file was specified, set default of /usr/local/etc/transmogrifier.conf if not configFile or not os.path.isfile(configFile): configFile = os.path.join("/", "usr", "local", "etc", "transmogrifier.conf") if not os.path.isfile(configFile): configFile = "transmogrifier.conf" ## Make sure the config file we plan to use exists and can be read by our parser cfgParser = "" if os.path.isfile(configFile): try: cfgParser = SafeConfigParser() cfgParser.read(configFile) if not basePath: basePath = cfgParser.get("GLOBAL","path") validModules = cfgParser.get("GLOBAL","modules").split(",") except: print "Error! Could reading global attributes from file at path: '%s' Error: %s" % (configFile,sys.exc_info()[0]) try: ## Get our debug status from our config only if we haven't already set it ## to true. if not debug: debug = cfgParser.getboolean("GLOBAL","debug") keepFiles = cfgParser.getboolean("GLOBAL", "keepfiles") except: settingsError=True else: print "Error! Could not find valid configuration file!" ##print "DEBUG: Actions:%s Targets:%s module:%s" % (actions,targets,module) ## If we have pooled actions and targets, and no module defined, process them if not module and actions and targets: myTargetObject = "" myTargetObjects = "" ## Make sure we have a target for each action that we have defined for theAction in actions: try: foundActionTargets = [] actionName = theAction["action"] if debug: print "DEBUG: Processing Action: %s" % actionName ## Make sure that our attempted targets jive with whether we're using ## fcsxml or fcsvr_client if "fcsvr_client" in theAction["sources"]: if len(theAction["sources"]) == 1 and not fcsvr_client: print "Action: %s requires fcsvr_client, cannot continue!" % actionName return 7 elif len(theAction["sources"]) > 1 and fcsvr_client and fcsvr_client_all: theAction["activeSource"] = "fcsvr_client" elif len(theAction["sources"]) > 1 and not fcsvr_client: theSource = "" if not "activeSource" in theAction or theAction["activeSource"] == "fcsvr_client": count = 0 while count < len(theAction["sources"]) and not theSource == "fcsvr_client": theSource = theAction["sources"][count] count += 1 if theSource: theAction["activeSource"] = theSource else: print "Error! Could not establish active source for action:%s" % actionName return 8 #### DETERMINE APPLICABLE TARGETS FOR ACTION #### ## Make sure that there is only one valid target. Here we build two ## lists for future use: 'myActionTarget' and 'myActionSecondTarget' ## (if applicable) myActionTarget = '' myActionSecondTarget = '' for theTarget in theAction["targets"]: ##print "theTarget: %s" % theTarget for myTargetKey,myTargetDict in targets.iteritems(): ##print "Searching for target: %s currentIndex: %s theTarget: %s" % (theTarget,myTargetKey,myTargetDict) if theTarget == myTargetDict['type'] and not myTargetKey == "secondTarget": foundActionTargets.append(myTargetKey) if len(foundActionTargets) > 1: print "Error! Ambiguous targets:%s specified for action:'--%s'" % (foundActionTargets,actionName) return 5 elif len(foundActionTargets) == 0: print "Error! No targets found for action:'--%s', requires one of: %s" % (actionName,",".join(theAction["targets"])) return 5 elif len(foundActionTargets) == 1: myActionTarget = targets[foundActionTargets[0]] ## If we are set to use a secondTarget, check it if useSecondTarget: if not 'secondTarget' in targets: print "Error! Action: %s requires more than one target!" % actionName foundSecondTarget = False for theTargetType in theAction["target2"]: ##print "theTargetType: %s, secondTargetType: %s" % (theTargetType,targets['secondTarget']['type']) if targets['secondTarget']['type'] == theTargetType: foundSecondTarget = True if foundSecondTarget: foundActionTargets.append('secondTarget') myActionSecondTarget = targets['secondTarget'] else: print "Error! Action: %s The specified second target does not meet our requirements!" return 5 ### BUILD TARGET OBJECTS FOR ACTION #### ## Iterate through each of our found targets and build their objects try: for targetName in foundActionTargets: if debug: print "DEBUG: Building object for target:%s" % targetName myTargetDict = targets[targetName] myDict = {} if myTargetDict["type"] == "asset" or myTargetDict["type"] == "assets": ## check to see if there is a loaded object for our target type if not "object" in myTargetDict or not myTargetDict["object"]: ## If not, build it based on the target's parameters if myTargetDict["target"] == "assetID": ##print "Building from assetID" assetID = myTargetDict["value"] myTargetObject = fcsxml.FCSVRClient(id=assetID,cfgParser=cfgParser) if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True elif myTargetDict["target"] == "assetTitle": ## print "Building from assetTitle" assetTitle = myTargetDict["value"]; myTargetObject = fcsxml.FCSVRClient(cfgParser=cfgParser) myTargetObject.initWithAssetTitle(assetTitle) if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True elif myTargetDict["target"] == "assetPath": fsPath = myTargetDict["value"] myTargetObject = fcsxml.FCSVRClient(cfgParser=cfgParser) if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True if not myTargetObject.initWithAssetFromFSPath(fsPath): raise fcsxml.FCSEntityNotFoundError(entityPath=fsPath) elif myTargetDict["target"] == "xmlin": xmlPath = myTargetDict["value"] myTargetObject = fcsxml.FCSXMLObject() myTargetObject.loadConfiguration(cfgParser) if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True myTargetObject.printLogs = True if not myTargetObject.setFile(xmlPath): print "Error! Could not read XML from path: '%s'" % xmlPath return 1 #### Apply filters to myTargetObject. #### ## If we don't meet our parameters, then clear out our target object if myTargetObject and filters: if 'mdSet' in filters and not myTargetObject.entityMetadataSet == filters['mdSet']: if debug: print ("Found Object: %s, but it does not match our" " metadata set of %s" % (myTargetObject.entityPath(),filters['mdSet'])) myTargetObject = False #### At this point we should have myTargetObject built. if (not "objectList" in myTargetDict or not myTargetDict["objectList"] and myTargetDict["type"] == "assets"): if myTargetDict["target"] == "assetsFromProductionID": productionID = myTargetDict["value"] myProduction = fcsxml.FCSVRClient(id=productionID,entityType="project") myProduction.loadConfiguration(cfgParser) if not debug: myProduction.printLogs = False else: myProduction.debug = True myProduction.printLogs = True ## Lookup our productions assets, apply filters if specified #### if filters: if 'mdSet' in filters: myTargetObjects = myProduction.assetsFromProduction(recurse=False,mdSet=filters['mdSet']) else: myTargetObjects = myProduction.assetsFromProduction(recurse=False) else: myTargetObjects = myProduction.assetsFromProduction(recurse=False) if (not "objectList" in myTargetDict or not myTargetDict["objectList"] and myTargetDict["type"] == "assets"): if myTargetDict["target"] == "assetsFromProjectID": projectID = myTargetDict["value"] myProject = fcsxml.FCSVRClient(id=projectID,entityType="asset",cfgParser=cfgParser) myProject.loadConfiguration(cfgParser) if not debug: myProject.printLogs = False else: myProject.debug = True ## Lookup our productions assets, apply filters if specified #### if filters: if 'mdSet' in filters: myTargetObjects = myProduction.assetsFromProject(recurse=False,mdSet=filters['mdSet']) else: myTargetObjects = myProduction.assetsFromProject(recurse=False) else: myTargetObjects = myProject.assetsFromProject() elif myTargetDict["type"] == "project": ## check to see if there is a loaded object for our target type if not "object" in myTargetDict or not myTargetDict["object"]: ## If not, build it based on the target's parameters if myTargetDict["target"] == "productionID": productionID = myTargetDict["value"] myTargetObject = fcsxml.FCSVRClient(id=productionID,entityType="project") myTargetObject.loadConfiguration(cfgParser) if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True elif myTargetDict["target"] == "productionTitle": productionTitle = myTargetDict["value"] myTargetObject = fcsxml.FCSVRClient(entityType="project", cfgParser=cfgParser).productionWithTitle(productionTitle, match='exact') if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True elif myTargetDict["target"] == "productionTitleLike": productionTitle = myTargetDict["value"] myTargetObject = fcsxml.FCSVRClient(entityType="project", cfgParser=cfgParser).productionWithTitle(productionTitle, match='substring') if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True elif myTargetDict["target"] == "createProductionWithTitle": productionTitle = myTargetDict["value"] try: newObject = fcsxml.FCSVRClient(entityType="project") try: myTargetObject = newObject.productionWithTitle(productionTitle) except: myTargetObject = newObject myTargetObject.loadConfiguration(cfgParser) except: pass if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True elif myTargetDict["target"] == "assetPath": fsPath = myTargetDict["value"] myTargetObject = fcsxml.FCSVRClient() myTargetObject.loadConfiguration(cfgParser) if not debug: myTargetObject.printLogs = False else: myTargetObject.debug = True if not myTargetObject.initWithAssetFromFSPath(fsPath): print "Error! Could not resolve asset from path: '%s'" % fsPath return 1 elif myTargetDict["type"] == "device": ## check to see if there is a loaded dict for our device target if not "deviceDict" in myTargetDict: ## If not, build it based on the target's parameters if myTargetDict["target"] == "deviceID": myDeviceID = myActionTarget["value"] myFCSVRClient = fcsxml.FCSVRClient() myFCSVRClient.printLogs = False myDict = myFCSVRClient.deviceWithID(myDeviceID) elif myTargetDict["target"] == "deviceName": myDeviceName = myActionTarget["value"] myFCSVRClient = fcsxml.FCSVRClient() myFCSVRClient.printLogs = False myDict = myFCSVRClient.deviceWithName(myDeviceName) elif myTargetDict["target"] == "devicePath": myDevicePath = myActionTarget["value"] myFCSVRClient = fcsxml.FCSVRClient() myFCSVRClient.printLogs = False myDict = myFCSVRClient.deviceWithPath(myDevicePath) print "Error! devicePath not implemented!" return 1 if myDict: myTargetDict["deviceDict"] = myDict if myTargetObject: myTargetDict['object'] = myTargetObject elif myTargetObjects: myTargetDict['objectList'] = myTargetObjects elif not myTargetObject and not myTargetObjects and not myDict: raise RuntimeError('No qualifying object found') except Exception,err: if debug: raise print "Error! Could not determine target from specified criteria for action: %s! Error: %s" % (actionName,err) exitCode=5 continue ### END BUILD TARGETS FOR ACTION #### ## At this point we should have up to two valid target dictionaries ## build: myActionTarget and myActionSecondTarget ## Each of these dicts should have an object loaded at index 'object' or ## 'objectList' if debug: print 'DEBUG: myActionTarget: %s' % myActionTarget if useSecondTarget: print 'DEBUG myActionSecondTarget: %s' % myActionSecondTarget #### PROCESS ACTION #### actionTargetType = myActionTarget["type"] ## Process Actions that use asset or production targets if actionName == "getField": myTargetObject = myActionTarget['object'] myValue = myTargetObject.valueForField(theAction['fieldName']) print '%s: %s' % (theAction['fieldName'],myValue) elif actionName == "getDBField": myTargetObject = myActionTarget['object'] myValue = myTargetObject.valueForDBField(theAction['fieldName']) print '%s: %s' % (theAction['fieldName'],myValue) elif actionName == "setField": #print "Setting Field:%s to value:%s" % (theAction["fieldName"],theAction["value"]) myTargetObjects = [] if 'objectList' in myActionTarget: myTargetObjects.extend(myActionTarget['objectList']) if 'object' in myActionTarget: myTargetObjects.append(myActionTarget['object']) theField = FCSXMLField(name=theAction["fieldName"],value=theAction["value"]) if len(myTargetObjects) > 0: for theObject in myTargetObjects: theObject.setField(theField) theObject.setMD() ## Sleep for a few seconds between values time.sleep(.5) elif actionName == "appendField": #print "Setting Field:%s to value:%s" % (theAction["fieldName"],theAction["value"]) ## Get the current value myTargetObjects = [] if 'objectList' in myActionTarget: myTargetObjects.extend(myActionTarget['objectList']) if 'object' in myActionTarget: myTargetObjects.append(myActionTarget['object']) ## If we have targets, iterate through them and append the field if len(myTargetObjects) > 0: for target in myTargetObjects: ## Get current field and value currentField = target.appendValueForField(fieldName=theAction['fieldName'], value=theAction['value'], useTimestamp = theAction['timestamp']) target.setMD() elif actionName == "setBoolField": #print "Setting Field:%s to value:%s" % (theAction["fieldName"],theAction["value"]) if not theAction["value"] or theAction["value"] == "false": theField = FCSXMLField(name=theAction["fieldName"],value=False,dataType="bool") else: theField = FCSXMLField(name=theAction["fieldName"],value=True,dataType="bool") if myTargetObject: myTargetObject.setField(theField) myTargetObject.setMD() if myTargetObjects: for theObject in myTargetObjects: if theObject.setField(theField): theObject.setMD() else: exitCode = 15 elif actionName == "getAssetID": if myTargetObject: print "ASSET_ID: %s" % myTargetObject.entityID if myTargetObjects: for myObject in myTargetObjects: print "ASSET_ID: %s" % myObject.entityID elif actionName == "getAssetPath": if myTargetObject: print "ASSET_PATH: %s" % myTargetObject.getFilePath() if myTargetObjects: for myObject in myTargetObjects: print "ASSET_PATH: %s" % myObject.getFilePath() elif actionName == "getEntityPath": if myTargetObject: print "ENTITY_PATH: %s" % myTargetObject.entityPath() elif myActionTarget['type'] == 'device': print "ENTITY_PATH: /dev/%s" % myDeviceDict['DEVICE_ID'] elif myTargetObjects: for myObject in myTargetObjects: print "ENTITY_PATH: %s" % myObject.entityPath() elif actionName == "getEntityMetadataSet": if myTargetObject: print "ENTITY_METADATASET: %s" % myTargetObject.entityMetadataSet elif actionName == "getFilePath": if myTargetObject: myFilePath = myTargetObject.getFilePath() if not myFilePath: myFilePath = "" print "FILE_PATH: %s" % myFilePath if myTargetObjects: for myObject in myTargetObjects: print "FILE_PATH: %s" % myObject.myFilePath() elif actionName == "getProxyPath": if myTargetObject: myFileProxyPath = myTargetObject.getFilePathForProxy() if not myFileProxyPath: myFileProxyPath = "" print "PROXY_PATH: %s" % myFileProxyPath elif actionName == "getEditProxyPath": if myTargetObject: myEditProxyPath = myTargetObject.getFilePathForEditProxy() if not myEditProxyPath: myEditProxyPath = "" print "EDITPROXY_PATH: %s" % myEditProxyPath elif actionName == "getThumbnailPath": if myTargetObject: myThumbnailPath = myTargetObject.getFilePathForThumbnail() if not myThumbnailPath: myThumbnailPath = "" print "THUMBNAIL_PATH: %s" % myThumbnailPath elif actionName == "getPosterFramePath": if myTargetObject: myPosterFramePath = myTargetObject.getFilePathForPosterFrame() if not myPosterFramePath: myPosterFramePath = "" print "POSTERFRAME_PATH: %s" % myPosterFramePath elif actionName == "getAssetTitle": if myTargetObject: myTitle = myTargetObject.valueForField("Title") if not myTitle: myTitle = "" print "ASSET_TITLE: %s" % myTitle elif actionName == "archive": if myTargetObject: print "Archiving Asset: %s" % myTargetObject.entityPath() try: myTargetObject.archive() except fcsxml.FCSAssetOfflineError,err: print " - %s" % eval(err.__str__()) return 9 if myTargetObjects: myRetCode = 0 for theObject in myTargetObjects: print "Archiving Asset: %s" % theObject.entityPath() try: theObject.archive() except fcsxml.FCSAssetOfflineError,err: print " - %s" % eval(err.__str__()) myRetCode = 9 if myRetCode == 9: return myRetCode elif actionName == "restore": if myTargetObject: print "Restoring Asset: %s" % myTargetObject.entityPath() myTargetObject.restore() if myTargetObjects: for theObject in myTargetObjects: print "Restoring Asset: %s" % theObject.entityPath() theObject.restore() elif actionName == "analyze": if myTargetObject: print "Analyzing Asset: %s" % myTargetObject.entityPath() myTargetObject.analyze(force=True) if myTargetObjects: for theObject in myTargetObjects: print "Analyzing Asset: %s" % theObject.entityPath() theObject.analyze(force=True) elif actionName == "getProductionID": if myTargetObject: print "PRODUCTION_ID: %s" % myTargetObject.entityID elif actionName == "getProductionTitle": if myTargetObject: print "PRODUCTION_TITLE: %s" % myTargetObject.valueForField('Title') elif actionName == "createProductionWithTitle": myTargetObject = myActionTarget['object'] productionTitle = myActionTarget['value'] if not myTargetObject.entityID: if debug: print "DEBUG: Creating production with title: '%s'" % productionTitle if not myTargetObject.createProduction(title=productionTitle): raise RuntimeError("Could not create production with title: %s!" % productionTitle) print "PRODUCTION_ID: %s" % myTargetObject.entityID elif actionName == "addToProduction": myTargetObject = myActionTarget['object'] myProduction = myActionSecondTarget['object'] if debug: print "DEBUG: myTargetObject:%s" % myTargetObject.entityPath() print "DEBUG: myProduction:%s" % myProduction.entityPath() if not myProduction.addMemberToProduction(member = myTargetObject): exitCode = 1 ## If this is a device-centric action, make sure we have a loaded ## device dict. elif 'Device' in actionName or 'device' in actionName: if not 'deviceDict' in myActionTarget: myTargetObject = myActionTarget['object'] ## Create our device field. myDeviceField = myTargetObject.loadField(fcsxml.FCSXMLField(name='Stored On',dbname='CUST_DEVICE')) myDeviceName = myDeviceField.value if debug: print "DEBUG: looking up device with name:%s" % myDeviceName myDeviceDict = myTargetObject.deviceWithName(myDeviceName) else: myDeviceDict = myActionTarget['deviceDict'] if actionName == 'getDeviceID': print "DEVICE_ID: %s" % myDeviceDict["DEVICE_ID"] if actionName == 'getDeviceName': print "DEVICE_NAME: %s" % myDeviceDict["DEVICE_NAME"] if actionName == 'getDevicePath': print 'DEVICE_PATH: %s' % myDeviceDict['DEV_ROOT_PATH'] except Exception, inst: if debug: raise print "ERROR: Failed to process action:%s Error: %s" % (actionName,inst) return 25 ## Return a 0 exit code on success return exitCode ## We are here if we bipassed the newer FCS-centric commands. From here no we ## are historical Code used for XML delivery and custom processing. if debug: print "DEBUG: Running older Codebase!" if module: print "DEBUG: Running for module: %s validModules: %s" % (module,','.join(validModules)) ''' ## if an xmlinPath was specified, make sure it exists. if "asset" in targets and targets["asset"]["source"] == "--xmlin": xmlinPath = "" xmlinPath and not os.path.isfile(xmlinPath): print "Error! No XML file was found at the specified path: '%s', exiting" % xmlinPath sys.exit(3) ''' ## Make sure we have a valid module if we're not just creating the support folder ## This step is very important as we dynamically create our objects based on the ## module string. if not module: module = "TransmogrifierTarget"; if not module in validModules and not action == "createSupportFolders": print "Invalid module: '%s'\n\tAllowed values: %s" % (module,",".join(validModules)) return 1 ## If our action is to upload or preflightCheck, we require a title to be ## specified (for every action but createSupportFolders) ## Todo: this all needs to be much more dynamic, the individual module needs a check against this if not action: print "No action has been provided, cannot continue! Run with --help to see syntax.\n" return 1 myActions = validActions(modules=validModules) if not action in myActions: print "Invalid Action: %s!\nAvailable Actions: %s" % (action,",".join(myActions)) return 6 if action != "createSupportFolders" and action != "batchStatusCheck" and action != "listFCSFields": if not fileTitle: print "An asset title must be provided when used with action: '%s'" % action return 2 elif action == "createSupportFolders": ## make sure we have a base path if basePath: if not module == "TransmogrifierTarget": if createSupportFolders(basePath,module): return 0 else: return 5 else: if createSupportFolders(basePath, validModules): return 0 else: return 5 else: helpMessage() return 1 ## Start our timer startTime = datetime.datetime.now() ## create our object base on our active module try: myObject = eval("%sObject()" % module) except: print "Could not create object: %sObject(), using default object!" % module myObject = TransmogrifierTargetObject() ## Set our debug status myObject.debug = debug if debug: myObject.printLogs = True if fcsvr_client: myObject.fcsvr_client = True if fcsvr_client_all: myObject.fcsvr_client_all = True ## load up the config file myObject.loadConfiguration(cfgParser) ## Determine our filename, FCS will not always output a file with it's full title. If ## the title has a '.' in it, it will truncate the filename to contain only chars ## preceeding the first . in the title, thus the file with title: ## "mymovie.foexport.mov" will be exported as mymovie.xml if fcsMajorVersion == "1.5": fileNameBase = os.path.splitext(fileTitle)[0] else: fileNameBase = re.sub(r'^(.*?)\..*$', r'\1', fileTitle) if not os.path.isdir(basePath): print "Path: '%s' does not exist!" % basePath return 2 if module == "TransmogrifierTarget": modulePath = basePath elif module == "sftp": modulePath = basePath else: modulePath = os.path.join(basePath, module) fileFound = False ## If we specified an XML file via the -i flag, we use that (it has already ## passed validation and will be set in xmlinPath. If no file was specified, ## we attempt to find it based on title passed with the -t flag. if xmlinPath: fileFound=True elif os.path.exists(os.path.join(modulePath,"xmlin","%s.xml" % (fileNameBase))): xmlinPath = os.path.join(modulePath,"xmlin","%s.xml" % (fileNameBase)) elif os.path.exists(os.path.join(basePath,"xmlin","%s.xml" % (fileNameBase))): xmlinPath = os.path.join(basePath,"xmlin","%s.xml" % (fileNameBase)) elif os.path.exists(os.path.join(basePath,"fcsvr_xmlout","%s.xml" % (fileNameBase))): xmlinPath = os.path.join(basePath,"fcsvr_xmlout","%s.xml" % (fileNameBase)) elif os.path.exists(os.path.join(basePath,"FCS/xmlin","%s.xml" % (fileNameBase))): ## if our xmlin file is found in the FCS directory, use that as our support dir modulePath = os.path.join(basePath,"FCS") fileFound=True if not xmlinPath and not (action == "batchStatusCheck" or action == "createSupportFolders" or action == "listFCSFields" or action == 'uploadMovies' or action == 'uploadImages'): print "Could not find file: '%s.xml' in paths: '%s/xmlin/', '%s/xmlin/', '%s/fcsvr_xmlout'" % (fileNameBase, modulePath, basePath,basePath) return 2 else: if not xmlinPath: xmlinPath = os.path.join(modulePath,"xmlin","%s.xml" % fileNameBase) ## Target-agnostic setup. myObject.setSupportPath(modulePath) myObject.fileBaseName = fileNameBase #### Perform our action #### if action == "batchStatusCheck" or action == "listFCSFields": if myObject.runFunction(action): return 0 else: return 1 elif action == "appendField" or action == "setField": if len(fields) > 0: myObject.setFCSXMLFile(xmlinPath) myFCSXML = myObject.fcsXMLObject for fieldName,field in fields.iteritems(): if field["action"] == "appendField": if field["value"]: newValue = field["value"] else: newValue = "\n" if field["timestamp"]: currentTime = datetime.datetime.fromtimestamp(time.mktime(datetime.datetime.now().timetuple())) newValue = "\n%s: %s\n" % (currentTime,newValue) myObject.appendFCSField(fieldName,"%s" % newValue) elif field["action"] == "setField": myObject.setFCSField(fieldName,"%s" % newValue) elif not action == "upload": ## If we're not uploading or doing a batchStatusCheck, load xml ## and pass action to the object. myObject.setFCSXMLFile(xmlinPath) if action == "autoKey": currentTime = datetime.datetime.fromtimestamp(time.mktime(datetime.datetime.now().timetuple())) myObject.appendFCSField("Shake History", "%s: Beginning Processing...\n" % currentTime) myObject.reportToFinalCutServer() if myObject.runFunction(action): endTime = datetime.datetime.now() processTime = endTime - startTime; statusMSG = "Action: %s successfully completed for module: %s. Elapsed time:'%s'" % (action, module,processTime) exitStatus = 0 else: statusMSG = "Action: %s failed to complete for module: %s\n\tError: %s" % (action, module, myObject.lastError) print statusMSG exitStatus = 1 if action == "autoKey": currentTime = datetime.datetime.fromtimestamp(time.mktime(datetime.datetime.now().timetuple())) myObject.appendFCSField("Shake History", "%s: %s\n" %(currentTime,statusMSG)) myObject.reportToFinalCutServer() return exitStatus else: myObject.setFCSXMLFile(xmlinPath) ## If we're uploading, log a message that we are uploading and report to FCS immediately. if myObject.preflightCheck(): ## Date/time string used for reporting currentTime = datetime.datetime.fromtimestamp(time.mktime(datetime.datetime.now().timetuple())) ## Update status prior to upload myObject.reportToFinalCutServer() ## Perform Upload myObject.upload() ## Delete our support files: if not keepFiles: print "Cleaning up files" myObject.deleteSupportFiles() else: print "keepfiles option set; skipping file cleanup" ## Report in for our final time. myObject.reportToFinalCutServer() return 0 ## If we called this file directly call main()
if __name__ == "__main__": try: sys.exit(main()) except Exception as inst: print "An unknown error occurred: %s:%s." % (inst.__class__.__name__,inst) raise sys.exit(99)