Module nukeFrontEnd
[hide private]
[frames] | no frames]

Source Code for Module nukeFrontEnd

  1  #!/bin/env python 
  2  ''' 
  3  A module for building pyNuke jobs.   
  4   
  5  These jobs use a persistent Nuke instance on the farm; a Dynamic Allocation jobtype. 
  6  ''' 
  7  #====================================== 
  8  #  $Revision: #17 $ 
  9  #  $Change: 17438 $ 
 10  #====================================== 
 11   
 12  import sys 
 13  import os 
 14   
 15  try: 
 16      import qb 
 17  except: 
 18      if 'QBDIR' in os.environ: 
 19          QBDIR = os.environ['QBDIR'] 
 20      else: 
 21          if os.name == 'posix': 
 22              if os.uname()[0] == 'Darwin': 
 23                  QBDIR = '/Applications/pfx/qube' 
 24              else: 
 25                  QBDIR = '/usr/local/pfx/qube' 
 26   
 27      sys.path.append('%s/api/python' % QBDIR) 
 28      import qb 
 29           
 30  try: 
 31      from qb import frontend 
 32      from qb.frontend import pythonFrontEnd as pythonFrontEnd 
 33  except ImportError: 
 34      from AppUI import frontend 
 35      from AppUI.frontend import pythonFrontEnd as pythonFrontEnd 
 36   
 37   
38 -class NukePythonJob(pythonFrontEnd.PythonChildJob):
39 - def __init__(self, nukeExe, nukeArgs=None, dev=False):
40 ''' 41 Function to initialize members of the class 42 43 @param nukeArgs: Optional arguments to use when starting the Nuke python session. 44 @type nukeArgs: C{dict} 45 46 @param dev: Set the 'dev' value for the Qube job, enables debug output on the farm. 47 @type dev: bool 48 ''' 49 super(NukePythonJob, self).__init__(dev=dev) 50 51 self['kind'] = 'nuke' 52 self['prototype'] = 'pyNuke' 53 54 pkg = { 55 'pyExecutable': nukeExe, 56 'nukeArgs': nukeArgs, 57 'smartAgenda': 1 58 } 59 self['package'].update(pkg) 60 61 self['package']['regex_errors'] = '\n'.join( 62 ['License failure', 63 'No license for product', 64 'FOUNDRY LICENSE ERROR REPORT', 65 'Can\'t read .* No such file or directory']) 66 67 self['package']['regex_highlights'] = '\n'.join( 68 ['^Nuke \d+\.\d+.*', 69 '^Nuke thread count: \d+', 70 '^Licence expires on.*']) 71 72 self.addJobCmds('''print "Nuke version: %s " % nuke.env['NukeVersionString']''') 73 self['agenda'] = []
74 75
76 -class NukeRenderJob(NukePythonJob):
77 - def __init__(self, nukeExe, frameRange, scriptPath, writeNodes=None, nukeArgs=None, jobName='', jobLabel='', dev=False):
78 ''' 79 Function to initialize members of the class 80 81 @param frameRange: A frame range string. 1-3,6-10x2 expands to [1,2,3,6,8,10] 82 @type frameRange: C{str} 83 84 @param scriptPath: The full disk path to a nuke script. 85 @type scriptPath: C{str} 86 87 @param writeNodes: A list of nuke Write node names; if a string is passed, it will be recast as a list. 88 @type writeNodes: C{list} 89 90 @param nukeArgs: Optional arguments to use when starting the Nuke python session. 91 @type nukeArgs: C{dict} 92 93 @param jobName: Optional qube job name 94 @type jobName: C{str} 95 96 @param jobLabel: Optional qube job label 97 @type jobLabel: C{str} 98 99 @param dev: Set the 'dev' value for the Qube job, enables debug output on the farm. 100 @type dev: bool 101 ''' 102 super(NukeRenderJob, self).__init__(nukeExe, nukeArgs=nukeArgs, dev=dev) 103 104 self.frameRange = frameRange 105 self['package']['frameRange'] = self.frameRange 106 self['package']['smartAgenda'] = True 107 108 self.scriptPath = scriptPath 109 self['package']['scriptPath'] = self.scriptPath 110 111 (self.scriptName, scriptExt) = os.path.splitext(os.path.basename(self.scriptPath)) 112 if jobName: 113 self['name'] = jobName 114 else: 115 self['name'] = 'Nuke render %s%s' % (self.scriptName, scriptExt) 116 117 if jobLabel: 118 self['label'] = jobLabel 119 120 if not writeNodes: 121 writeNodes = [] 122 elif isinstance(writeNodes, str): 123 writeNodes = [writeNodes] 124 self.writeNodes = sorted(writeNodes) 125 self['package']['writeNodes'] = self.writeNodes 126 127 if nukeArgs: 128 self['package']['nukeArgs'] = ' '.join(['%s %s' % (x[0], x[1]) for x in nukeArgs.items()]) 129 130 self['package']['regex_outputPaths'] = 'Writing (.*) took [0-9.\-]+ seconds' 131 132 self.addJobCmds('import nukescripts') 133 self.addJobCmds(self.getQubeFileNameFilterCmds()) 134 135 nuke_script = self.scriptPath 136 if not nuke_script.startswith('"'): 137 nuke_script = '"%s"' % nuke_script 138 self.addJobCmds('nuke.scriptOpen(%s)' % nuke_script) 139 140 if not self.writeNodes: 141 self.addJobCmds('''allWriteNodes = sorted([x.name() for x in nuke.allNodes() if x.Class()=='Write'])''') 142 143 self['agenda'] = self._buildAgenda()
144
146 ''' 147 Build the command string that will create a Nuke fileNameFilter function that will fetch and 148 iterate over the worker's worker_path_map dictionary. 149 150 @return: the necessary Nuke python commands to initialize Nuke's internal path mapping 151 @rtype: C{list} 152 ''' 153 cmds = [] 154 155 cmds.append(''' 156 #================================================= 157 # Setting up path translation FilenameFilter 158 #================================================= 159 def qubeWorkerFilenameFilter(filename): 160 import qb 161 xlatedPath = qb.convertpath(filename, qb.workerpathmap()) 162 return xlatedPath 163 164 nuke.addFilenameFilter(qubeWorkerFilenameFilter) 165 #================================================= 166 # Done... 167 #================================================= ''' ) 168 return cmds
169
170 - def _buildAgenda(self):
171 ''' 172 Create an agenda for the job, complete with per-frame python commands. 173 174 @return: The populated work agenda for the job 175 @rtype: C{dict} 176 ''' 177 agenda = [] 178 for frame in [x['name'] for x in qb.genframes(self.frameRange)]: 179 if self.writeNodes: 180 for node in self.writeNodes: 181 cmds = [] 182 work = {'name': '%s@%04d' % (node, int(frame)), 183 'package': {'commands': cmds} 184 } 185 186 fmt = {'n': node, 'f': frame} 187 cmds.append('''writeNode = nuke.toNode('%(n)s')''' % fmt) 188 cmds.append('''print "Rendering Write node: %(n)s"''' % fmt) 189 cmds.append('''filename = nukescripts.replaceHashes( writeNode['file'].value() ) % nuke.frame()''') 190 cmds.append('''pathTranslated = qubeWorkerFilenameFilter(filename)''') 191 cmds.append('''if filename != pathTranslated: print "\\n\\t%s\\n\\t-> %s\\n" % (filename, pathTranslated)''') 192 cmds.append('resultBool = nuke.execute("%(n)s", %(f)s, %(f)s, 1)' % fmt) 193 cmds.append('''if resultBool == False: raise Exception, "Failure encountered processing node '%(n)s at frame%(f)s'"''' % fmt) 194 cmds.append('sys.stdout.flush()') 195 196 agenda.append(work) 197 else: 198 cmds = [] 199 work = {'name': '%s' % frame, 200 'package': {'commands': cmds} 201 } 202 203 fmt = {'f': frame} 204 cmds.append(''' 205 for node in allWriteNodes: 206 print 'Rendering Write node: %%s' %% node 207 resultBool = nuke.execute('%%s' %% node, %(f)s, %(f)s, 1) 208 if resultBool == False: 209 raise Exception, "Failure encountered processing node '%%s at frame%(f)s' %% node" 210 sys.stdout.flush() 211 ''' % fmt) 212 agenda.append(work) 213 214 return agenda
215 216 217 if __name__ == '__main__': 218 ''' 219 A "hello world", meant to show how to build and submit a Nuke dynamic allocation job using the pythonChildJob framework. 220 ''' 221 # It's only neccessary to setsupervisor() if you have multiple supervisors in your environment 222 #qb.setsupervisor('build01') 223 224 jobList = [] 225 226 nukeExe = '/Applications/Nuke8.0v4/Nuke8.0v4.app/Contents/MacOS/Nuke8.0v4' 227 nukeExe = '//NEWTON/Pypeline/bin/current/all/nuke8v6_.bat' 228 nukeScript = '//eru/py_dev/qube_test/nuke/nuke_render.nk' 229 nukeArgs = {} 230 231 jobA = NukeRenderJob(nukeExe, frameRange='1-10', scriptPath=nukeScript, writeNodes=[], nukeArgs=nukeArgs) 232 jobA['cpus'] = 4 233 jobA['max_cpus'] = 0 234 jobA['name'] += ' 1 node' 235 jobA['reservations'] = 'host.processors=1+5' 236 jobList.append(jobA) 237 238 nukeScript = '/Users/jburk/test/nuke/test_2nodes.nk' 239 jobB = NukeRenderJob(nukeExe, frameRange='1-20', scriptPath=nukeScript, nukeArgs=nukeArgs) 240 jobB['cpus'] = 4 241 jobB['name'] += ' 2 nodes' 242 #jobList.append(jobB) 243 244 if '--arc' in sys.argv: 245 arcSize = qb.archivejob('job.qja', jobA, format=qb.QB_API_BINARY) 246 print 'job.qja: %s bytes' % arcSize 247 else: 248 for j in qb.submit(jobList): 249 print 'submitted: %(id)s' % j 250 251 sys.exit() 252