def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        helper = PuliActionHelper(cleanTemp=True)

        # convert the paths
        prodPath = helper.mapPath(arguments[PROJECT])
        arguments[RENDER_DIR] = helper.mapPath(arguments[RENDER_DIR])
        arguments[SCENE] = helper.mapPath(arguments[SCENE])

        env = helper.getEnv(am_version=arguments[ARNOLD_VERSION],
                            maya_version=arguments[MAYA_VERSION],
                            shave_version=arguments[SHAVE_VERSION],
                            crowd_version="",
                            home=os.environ["HOME"],
                            job=os.path.basename(prodPath),
                            jobdrive=os.path.dirname(prodPath),
                            applis=helper.mapPath("/s/apps/lin"),
                            use_shave=0)

        # init log
        helper.printStartLog("mayarunner", "v1.0")

        cmdArgs = helper.buildMayaCommand("MikserActionMayaRender", arguments, [prodPath, arguments[SCENE]], env)
        print "Executing command : %s" % str(cmdArgs)
        comp = 0.1
        updateCompletion(comp)
        ret = helper.execute(cmdArgs, env)
        print ret
 def execute(self, arguments, updateCompletion, updateMessage):
     # init the helper
     helper = PuliActionHelper()
     # get input sequence
     seq = helper.mapPath(arguments[SCENE])
     parentDir = os.path.dirname(seq)
     self.srcDirName = os.path.basename(parentDir)
     # convert the paths
     prodPath = helper.mapPath(arguments[PROJECT])
     # get start and end
     self.start = arguments[START]
     self.end = arguments[END]
     # cmdline
     self.cmd = helper.mapPath("/s/apps/lin/bin/exrmakescanlined")
     # temp dir
     self.tmpDir = os.path.join(prodPath, "_admin", "mikser", "tmp")
     if not os.path.isdir(self.tmpDir):
         os.mkdir(self.tmpDir)
     os.path.walk(parentDir, self.visit, "")
    def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        helper = PuliActionHelper(cleanTemp = True)

        env = {}
        env["RLM_LICENSE"] = "2764@dispatch:2375@kiwi:5053@kiwi"

        # init log
        helper.printStartLog("milkrunner", "v1.0")

        # cmd path
        cmdArgs = [helper.mapPath("/s/apps/lin/Milk/milk")]

        # pre args
        if PRE_ARGS in arguments.keys() and len(arguments[PRE_ARGS]) != 0:
            cmdArgs.extend(shlex.split(arguments[PRE_ARGS]))

        cmdArgs += ["-fi", arguments[SCENE]]
        cmdArgs += ["-ti","%s-%s" % (arguments[START],arguments[END])]

        # middle args
        if MID_ARGS in arguments.keys() and len(arguments[MID_ARGS]) != 0:
            cmdArgs.extend(shlex.split(arguments[MID_ARGS]))

        cmdArgs += ["-to","%s-%s" % (arguments[START],arguments[END])]

        # resize arg
        if WIDTH in arguments.keys() and HEIGHT in arguments.keys() and len(str(arguments[WIDTH])) != 0 and len(str(arguments[HEIGHT])) != 0:
            cmdArgs += ["-resize", str(arguments[WIDTH]), str(arguments[HEIGHT])]

        # fileout arg
        cmdArgs += ["-fo", arguments[OUTPUT_IMAGES]]

        # post args
        if POST_ARGS in arguments.keys() and len(arguments[POST_ARGS]) != 0:
            cmdArgs.extend(shlex.split(arguments[POST_ARGS]))

        # overwrite
        if int(arguments[OVERWRITE]):
            cmdArgs.append("-overwrite")
        else:
            cmdArgs.append("-pass")

        # launch cmd
        updateCompletion(0)
        print cmdArgs
        helper.execute(cmdArgs, env)
        updateCompletion(1)
        print "done."
    def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        helper = PuliActionHelper()
        ###
        #Pull info from decomposer
        ###
        mayaScene = helper.mapPath(arguments[SCENE])
        mayaSceneRootName = '3d_pr'
        if mayaScene.count(mayaSceneRootName) == 0:
            # TODO: a real mikser warning and exit
            print 'Warning: unable to find the maya root directory'
            
        #check existence and writability of render dir
        renderDir = arguments[RENDER_DIR]
        helper.checkExistenceOrCreateDir(renderDir, 'render dir')
        if not os.access(renderDir, os.W_OK):
            print 'Error: unable to write in %s' % renderDir
            raise Exception
        
        self.melArgs[1] = str(arguments[START])
        self.melArgs[2] = str(arguments[END])
        self.melArgs[5] = arguments[RENDER_DIR]
        self.melArgs[7] = os.path.splitext(arguments[OUTPUT_IMAGE])[0]
        try:
            self.melArgs[3] = 'OneFile' if int(arguments[ONE_FILE]) == 1 else 'OneFilePerFrame'
        except KeyError:
            pass
        self.updateMelArgs(11, SIMULATION_RATE, arguments)
        self.updateMelArgs(12, SAVE_RATE, arguments)
        self.updateMelArgs(16, DENSITY, arguments)
        self.updateMelArgs(17, VELOCITY, arguments)
        self.updateMelArgs(18, TEMPERATURE, arguments)
        self.updateMelArgs(19, FUEL, arguments)
        self.updateMelArgs(20, COLOR, arguments)
        self.updateMelArgs(21, TEXTURE, arguments)
        self.updateMelArgs(22, FALLOFF, arguments)
        melArgsString = ' '.join(self.melArgs)
        argsList = ['mel', melArgsString]
        argsList += [FLUID, arguments[FLUID]]
        readyForJsonArgs = '"%s"' % str(argsList) # this formatting is needed in MikserCommonRender.MikserCommonHeaderAndInit
      
        ###
        #Env set up
        ###
        prodPath = helper.mapPath(arguments[PROJECT])
        env = helper.getEnv(maya_version=arguments['maya'], 
                            home=os.environ["HOME"], 
                            job=os.path.basename(prodPath), 
                            jobdrive=os.path.dirname(prodPath), 
                            applis=helper.mapPath("/s/apps/lin"))

        ###
        #Additionnal arguments
        ###
        # maya's python
        if platform.system() == 'Linux':
            mayaPython = env["MAYA_LOCATION"] + "/bin/python-bin"
        else:
            mayaPython = env["MAYA_LOCATION"] + "\\bin\\mayapy.exe"

        # script doing the actual simulation baking process
        mayaGenFluidScript = '/s/apps/lin/maya/scripts/MikserActionMayaGenFluidCache.py'

        ###
        #Execute the command line
        ###
        argsListN = [mayaPython, mayaGenFluidScript, readyForJsonArgs, prodPath, mayaScene]
        
        print 'Launching maya python (%s)' % mayaPython
        print 'With script: %s' % mayaGenFluidScript
        print 'And arguments: %s' % readyForJsonArgs
        print 'Using maya scene: %s' % mayaScene
        
        updateCompletion(0)
        helper.execute(argsListN, env=env)
        # update the completion
        updateCompletion(0.7)
        
        ###
        #Check cache file existence
        ###
        cacheFile = os.path.join(arguments[RENDER_DIR], arguments[OUTPUT_IMAGE]+'.xml')
        if not os.path.exists(cacheFile):
            print "Error: cache file %s has not been written" % cacheFile
            raise Exception
        
        ###
        #This is the end
        ###
        print "\n\n---- %s has been written SUCCESSFULLY ----" % cacheFile
class NukeRunner(CommandRunner):
    def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        self.helper = PuliActionHelper(cleanTemp=True)

        # convert the paths
        prodPath = self.helper.mapPath(arguments[PROJECT])
        arguments[NUKE_SCENE] = self.helper.mapPath(arguments[NUKE_SCENE])
        outImages = self.helper.mapPath(arguments[OUTPUT_IMAGES])

        # set the env
        env = self.helper.getEnv(nuke_rep=arguments[NUKE_VERSION],
                                 home=os.environ["HOME"],
                                 job=os.path.basename(prodPath),
                                 jobdrive=os.path.dirname(prodPath),
                                 applis=self.helper.mapPath("/s/apps/lin"))

        # init log
        self.helper.printStartLog("NukeRunner", "1.2")

        # replace the local nuke scene argument in the argslist
        if outImages != "":
            localNukeScene = self.updateOutputFiles(arguments[NUKE_SCENE], outImages, arguments[WRITE_NODE])

        cmdArgs = self.helper.buildNukeCommand(arguments, localNukeScene)

        updateCompletion(0.1)
        updateMessage("Executing command %s" % cmdArgs)
        print "\nExecuting command : %s\n" % cmdArgs
        sys.stdout.flush()

        out = subprocess.Popen(cmdArgs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, env=env)
        begintime = time.time()
        completedFrames = 0
        totalFrames = (int(arguments[END]) - int(arguments[START]) + 1) // int(arguments[STEP])
        if arguments.get("views", ''):
            totalFrames = totalFrames * len(arguments["views"].split(","))
        while True:
            line = out.stdout.readline()
            if not line:
                break
            print line,
            sys.stdout.flush()
            if re.match(FRAME_WRITE_PATTERN, line):
                completedFrames += 1
                print "%s -- frame %d of %d rendered --" % (time.strftime('[%H:%M:%S]', time.gmtime(time.time() - begintime)), completedFrames, totalFrames)
                sys.stdout.flush()
                updateMessage("%d frames rendered" % completedFrames)
                updateCompletion(float(completedFrames) / totalFrames)
            if completedFrames == totalFrames:
                print "\nrender done."
                updateMessage("render done.")
                updateCompletion(1)
                break
        out.terminate()
        if completedFrames != totalFrames:
            raise Exception("Incomplete job: %d/%d images rendered" % (completedFrames, totalFrames))

    def updateOutputFiles(self, srcNukeFilePath, outImages, writeNode):
        if self.helper.isLinux():
            tempDir = "/tmp"
        else:
            tempDir = "T:/Temp"
            outImages = outImages.replace("\\", "/")

        date = datetime.datetime.now()
        dateStr = date.strftime("%d%m%Y_%H_%M_%S")
        localNukeScene = os.path.join(tempDir, os.path.basename(srcNukeFilePath) + "_" + dateStr + ".nk")

        ## Creating render images dir
        outFolder = os.path.dirname(outImages)
        if "%v" in outFolder or "%V" in outFolder:
            ## test parsing views
            srcNukeFile = open(srcNukeFilePath, 'r')
            lines = srcNukeFile.readlines()
            srcNukeFile.close()
            lines.reverse()

            index = lines.index(" name " + writeNode + "\n")

            onlyLeft = False
            onlyRight = False

            for i in range(index, len(lines)):
                if 'views {' in lines[i]:
                    if 'left' in lines[i]:
                        onlyLeft = True
                    else:
                        onlyRight = True
                if 'Write {' in lines[i]:
                    break
            if "%v" in outFolder:
                if not onlyRight:
                    self.helper.checkExistenceOrCreateDir(outFolder.replace('%v', 'l'), "render dir left")
                if not onlyLeft:
                    self.helper.checkExistenceOrCreateDir(outFolder.replace('%v', 'r'), "render dir right")
            elif "%V" in outFolder:
                if not onlyRight:
                    self.helper.checkExistenceOrCreateDir(outFolder.replace('%V', 'left'), "render dir left")
                if not onlyLeft:
                    self.helper.checkExistenceOrCreateDir(outFolder.replace('%V', 'right'), "render dir right")
        else:
            self.helper.checkExistenceOrCreateDir(outFolder, 'render dir')

        srcNukeFile = open(srcNukeFilePath, 'r')
        ## Creating nuke tmp out file in tempDir
        dstNukeFile = open(localNukeScene, 'w')

        ## Copying nuke file in tempFile
        contentStr = srcNukeFile.read()
        srcNukeFile.close()
        dstNukeFile.write(contentStr)

        outImagesPadding = outImages.count("#")
        if outImagesPadding:
            outStrPadding = "%0" + str(outImagesPadding) + "d"
            inStrPadding = ""
            inStrPadding = inStrPadding.rjust(outImagesPadding, "#")
            outImages = outImages.replace(inStrPadding, outStrPadding)

        dstNukeFile.write("\n#### ADDED BY PULI : " + dateStr + " ###\n")

        ## Pre scripts
#        dstNukeFile.write("\n## PRE SCRIPTS ###\n\n")
#        for scripPath in inScripts:
#            dstNukeFile.write("load \"" + scripPath + "\"\n")

        # Write Node
        dstNukeFile.write("\n## WRITE NODE ###\n")
        dstNukeFile.write("\nknob " + writeNode + ".file \"" + outImages + "\"\n")

        print "\nLocal Nuke scene created : '" + localNukeScene + "'."
        dstNukeFile.close()

        return localNukeScene
    def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        helper = PuliActionHelper(cleanTemp = True)

        start = int(arguments[START])
        end = int(arguments[END])
        padding = int(arguments[PADDING])
        prefix = str(arguments[OUTPUT_IMAGE])

        # convert the paths
        prodPath = helper.mapPath(arguments[PROJECT])
        arguments[RENDER_DIR] = helper.mapPath(arguments[RENDER_DIR])
        arguments[SCENE] = helper.mapPath(arguments[SCENE])

        # set the env
        env = helper.getEnv(am_version=arguments[ARNOLD_VERSION],
                            maya_version=arguments[MAYA_VERSION],
                            shave_version=arguments[SHAVE_VERSION],
                            home=os.environ["HOME"],
                            job=os.path.basename(prodPath),
                            jobdrive=os.path.dirname(prodPath),
                            applis=helper.mapPath("/s/apps/lin"))

        helper.printStartLog("MentalRayRunner", "v1.1")
        cmdArgs = helper.buildMayaCommand("MikserActionMentalRayRender", arguments, [prodPath, arguments[SCENE]], env)
        print "Executing command : %s" % str(cmdArgs)
        comp = 0.1
        updateCompletion(comp)
        ret = helper.execute(cmdArgs, env)
        if ret != 0:
            raise Exception("A problem occured in the render script, see log")

        # check images
        layer2Render = []
        if RENDER_LAYERS in arguments:
            layer2Render = str(arguments[RENDER_LAYERS]).split(",")
        if len(layer2Render):
            for layer in layer2Render:
                for frameInt in range(start, end+1):
                    frameStr = str(frameInt).rjust(padding, "0")
                    # FIXME improve this...
                    # check the file
                    if layer == "defaultRenderLayer":
                        layerfolder = "masterLayer"
                    else:
                        layerfolder = layer
                    renderdir = str(arguments[RENDER_DIR]) + "/" + layerfolder + "/"
                    filename = renderdir + prefix + "-" + layer + "." + frameStr + "." + str(arguments[FORMAT])
                    print "Checking \"%s\"..." % filename
                    if not os.path.isfile(filename):
                        raise Exception("File does not exist")
                    else:
                        print "OK."
        else:
            for frameInt in range(start, end+1):
                frameStr = str(frameInt).rjust(padding, "0")
            # check the file
            filename = str(arguments[RENDER_DIR]) + "/" + prefix + "." + frameStr + "." + str(arguments[FORMAT])
            print "Checking \"%s\"..." % filename
            if not os.path.isfile(filename):
                raise Exception("File does not exist")
            else:
                print "OK."

        updateCompletion(1)
        print "\nrender done."
    def execute(self, arguments, updateCompletion, updateMessage):
        frameCompletionPattern = re.compile("\| (.*)% done .* rays/pixel")

        # init the helper
        helper = PuliActionHelper(cleanTemp=True)

        # convert the paths
        projPath = helper.mapPath(arguments[PROJECT])
        prodPath = helper.mapPath(arguments[PROD])
        arguments[OUTPUT_ASS_FILE] = helper.mapPath(arguments[OUTPUT_ASS_FILE])
        arguments[RENDER_DIR] = helper.mapPath(arguments[RENDER_DIR])
        arguments[SCENE] = helper.mapPath(arguments[SCENE])

        # set the env
        use_shave = 0
        if MTOA_EXTENSIONS in arguments.keys() and SHAVE_VERSION in arguments[MTOA_EXTENSIONS]:
            use_shave = 1
        crowd_version = ""
        if CROWD_VERSION in arguments.keys():
            crowd_version = arguments[CROWD_VERSION]
        env = helper.getEnv(am_version=arguments[ARNOLD_VERSION],
                            maya_version=arguments[MAYA_VERSION],
                            shave_version=arguments[SHAVE_VERSION],
                            crowd_version=crowd_version,
                            home=os.environ["HOME"],
                            job=os.path.basename(prodPath),
                            jobdrive=os.path.dirname(prodPath),
                            applis=helper.mapPath("/s/apps/lin"),
                            use_shave=use_shave)

        # init log
        helper.printStartLog("mtoarunner", "v2.1")

        # check existence of output ass folders
        helper.checkExistenceOrCreateDir(arguments[OUTPUT_ASS_FILE], "output ass folder")
        helper.checkExistenceOrCreateDir(arguments[RENDER_DIR], "render dir")

        # MtoA Extensions
        extensionsNodesSearchPath = []
        if MTOA_EXTENSIONS in arguments.keys():
            xtensions = arguments[MTOA_EXTENSIONS]
            addonPath = env["ARNOLD_LOCATION"] + "/add-ons"
            if xtensions == "<All>":
                # List directories in add-ons to add all extensions
                print "Will force load of all MtoA extensions available :"
                if not os.path.isdir(addonPath):
                    print "No Extension dir found"
                else:
                    print "Search in " + addonPath
                    fileList = os.listdir(addonPath)
                    if fileList:
                        fileList.sort()
                        nb = 0
                        for nb, extfile in enumerate(fileList):
                            if os.path.isdir(addonPath + "/" + extfile):
                                print " [ %s ]" % (extfile)
                                arguments['le'] = extfile
                                if os.path.isdir(os.path.join(addonPath, extfile, "nodes")):
                                    extensionsNodesSearchPath += ["-l", os.path.join(addonPath, extfile, "nodes")]
                                if nb == 0:
                                    extStr = extfile
                                else:
                                    extStr = extStr + ',' + extfile
                        if nb:
                            arguments['le'] = extStr
                        else:
                            print "No Extension found"
                    else:
                        print "Empty directory."
            else:
                lesExt = xtensions.split(",")
                for xt in lesExt:
                    extName = xt.strip()
                    if extName:
                        print "Will force load of MtoA Extension : [ %s ]" % (extName)
                        if os.path.isdir(os.path.join(addonPath, extName, "nodes")):
                            extensionsNodesSearchPath += ["-l", os.path.join(addonPath, extName, "nodes")]
                arguments['le'] = xtensions

        # Add arg to write outputs image files list
        outputsFile = '/datas/tmp/filestocheck_' + datetime.datetime.now().strftime('%y%m%d_%H%M%S')
        arguments['ifo'] = outputsFile

        cmdArgs = helper.buildMayaCommand("MikserActionMtoARender", arguments, [projPath, arguments[SCENE]], env)

        # Execute the command line that will export the ass
        print '\nLaunch export command "%s"' % cmdArgs
        comp = 0.0
        updateCompletion(comp)
        ret = helper.execute(cmdArgs, env=env)
        print '===================================================='
        print '  MikserActionMtoARender returns with code %d' % (ret)
        print '===================================================='
        if ret != 0:
            print '  Export failed, exiting...'
            raise Exception('  Export failed, exiting...')

        # update the completion
        #comp = 0.3
        #updateCompletion(comp)

        # Extra kick flags
        extraKickFlags = []
        if EXTRA_KICK_FLAGS in arguments.keys():
            extraKickFlags = self.parseExtraKickArgs(arguments[EXTRA_KICK_FLAGS])

        # kick the ass to render images
        # kick -l /s/apps/arnold/mArny2.27.21/shaders ./RE-sq14sh20-all_z-v002.1019.ass -dcau -log -v 2
        # au lieu de
        # kick -nstdin -dp -i /datas/tmp/assfiles/RE-sq14sh20-all_z-v002.1019.ass
        start = int(arguments[START])
        end = int(arguments[END])
        totalFrames = end - start + 1

        tiledDestination = arguments[RENDER_DIR] + "_Tiled"
        helper.checkExistenceOrCreateDir(tiledDestination, "tiled directory")

        for frameInt in range(start, end + 1):
            argList = [env["ARNOLD_LOCATION"] + "/bin/kick"]
            frameStr = str(frameInt).rjust(int(arguments[PADDING]), "0")
            # add the arguments to the kick command line
            argList += ["-l", env["ARNOLD_LOCATION"] + "/nodes"]
            # add extensions paths
            argList += extensionsNodesSearchPath
            assFilePath = arguments[OUTPUT_ASS_FILE] + "/" + arguments[OUTPUT_IMAGE] + "." + frameStr + ".ass"
            # support for compress ass
            if COMPRESS_ASS in arguments.keys():
                if int(arguments[COMPRESS_ASS]):
                    assFilePath += ".gz"
            if assFilePath.find(" ") != -1:
                assFilePath = "\"" + assFilePath + "\""
            argList += [assFilePath]
            argList += ["-nokeypress"]
            argList += ["-dp"]
            argList += ["-dw"]
            argList += ["-log"]
            # no license check
            if NO_LIC_CHECK in arguments.keys():
                if int(arguments[NO_LIC_CHECK]):
                    argList += ["-sl"]
            # verbose level
            if VERBOSE_LEVEL in arguments.keys():
                argList += ["-v", str(arguments[VERBOSE_LEVEL])]
            # number of threads
            if NUMBER_OF_THREADS in arguments.keys():
                argList += ["-t", str(arguments[NUMBER_OF_THREADS])]
            # Extra kick flags
            argList += extraKickFlags

            # kick the command
            print "\nKicking command : " + " ".join(argList)

            #kickret = helper.execute(argList, env=env)

            out = subprocess.Popen(argList, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, env=env)
            rc = None
            while rc is None:
                line = out.stdout.readline()
                if not line:
                    break
                print line,
                sys.stdout.flush()
                fcp = frameCompletionPattern.search(line)
                if fcp:
                    framecomp = float(fcp.group(1).strip())
                    fc = float(framecomp / 100) / float(totalFrames)
                    updateCompletion(comp + fc)
                rc = out.poll()

            out.communicate()
            rc = out.poll()
            print '===================================================='
            print '  kick command returns with code %d' % rc
            print '===================================================='
            if rc != 0:
                print '  Kick command failed...'
                raise Exception('  Kick command failed...')
            comp += 1.0 / float(totalFrames)

            # suppression of ass files
            if not int(arguments[LEAVE_ASS_FILES]):
                try:
                    os.remove(assFilePath)
                except OSError:
                    print "\nFailed to remove '" + assFilePath + "'\n"
            else:
                print "\nLeaving Ass extfile on disk : '" + assFilePath + "'\n"

            # Check the output image files by reading outputs extfile
            # Make them scanlined if in exr format
            self.invertedFormatsMap = {'1': 'jpg',  '2': 'tif', '3': 'exr', '4': 'png'}
            print "\nCheck render outputs :"
            outputsByFrame = outputsFile + '.' + frameStr
            lines = []
            try:
                outputsFileHdl = open(outputsByFrame, "r")
                lines = outputsFileHdl.readlines()
                outputsFileHdl.close()
            except IOError:
                filename = arguments[RENDER_DIR] + "/" + arguments[OUTPUT_IMAGE] + "." + frameStr + "." + self.invertedFormatsMap[str(arguments[FORMAT])]
                lines = [filename]

            for line in lines:
                # Check
                filename = line.rstrip()
                print "> %s" % filename
                if not os.path.exists(filename):
                    raise Exception("file does not exist!")
                print "  OK."

                # exrmakescanlined
                make_scanlined = 1
                if MAKE_SCANLINED in arguments:
                    make_scanlined = int(arguments[MAKE_SCANLINED])
                if make_scanlined:
                    extension = os.path.splitext(filename)[1][1:]
                    if extension == 'exr':
                        print "  Make exr scanlined..."
                        exrscanlinedCmdArgs = ["/s/apps/lin/bin/exrmakescanlined"]
                        exrscanlinedCmdArgs.append("-v")
                        exrscanlinedCmdArgs.append(filename)
                        dest = '/tmp/' + os.path.basename(filename)
                        exrscanlinedCmdArgs.append(dest)
                        output, error = subprocess.Popen(exrscanlinedCmdArgs, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
                        #print output
                        if "nothing to do" in output:
                            print "    Nothing to do."
                        elif error:
                            print output
                            print error
                        else:
                            # move the extfile in a tiled dir and replace it with the new extfile
                            oldy = filename.replace(arguments[RENDER_DIR], tiledDestination)
                            print '    Replace image by scanlined version and move it to : '
                            print '      ' + oldy
                            shutil.move(filename, oldy)
                            shutil.move(dest, filename)
                            # idiff comparison
                            idiffcmd = ["/s/apps/lin/bin/idiff"]
                            idiffcmd.append(filename)
                            idiffcmd.append(oldy)
                            devnull = open('/dev/null', 'w')
                            idiffret = subprocess.Popen(idiffcmd, env=os.environ, stdout=devnull).wait()
                            #idiffret = helper.execute(idiffcmd, env=os.environ)
                            # if no difference, delete the tiled version
                            if idiffret == 0:
                                print "       idiff : Tiled and Scanlined images match, removing Tiled version..."
                                os.remove(oldy)
                                print "         Tiled version removed."
                            # FIXME check permissions
                            import stat
                            st = os.stat(filename)
                            if not bool(st.st_mode & stat.S_IRGRP) or not bool(st.st_mode & stat.S_IWGRP):
                                logtemp = open("/s/apps/lin/puli/tmplog.csv", 'a')
                                import socket
                                logtemp.write("%s\t%s\t%s\tmtoa\t%s\t%s\n" % (filename, socket.gethostname(), os.path.basename(prodPath), oct(stat.S_IMODE(st.st_mode)), time.strftime('%H:%M', time.localtime())))
                                logtemp.close()

            # Suppress image outputs list
            try:
                os.remove(outputsByFrame)
            except OSError:
                print "\nFailed to remove %s\n" % outputsByFrame

            # update completion
            #comp += 0.7 / totalFrames
            #updateCompletion(comp)
        updateCompletion(1)
        print "\nrender done."
    def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        helper = PuliActionHelper()

        # convert the paths
        prodPath = helper.mapPath(arguments[PROJECT])

        env = helper.getEnv(am_version=arguments[ARNOLD_VERSION],
                            maya_version=arguments[MAYA_VERSION],
                            shave_version=arguments[SHAVE_VERSION],
                            home=os.environ["HOME"],
                            job=os.path.basename(prodPath),
                            jobdrive=os.path.dirname(prodPath),
                            applis=helper.mapPath("/s/apps/lin"))
        # this is necessary for the python-bin of maya to work properly
        env["PYTHONHOME"] = env["MAYA_LOCATION"]

        # init log
        helper.printStartLog("MarnyRunner", "v1.1")

        # check existence of output ass folders
        helper.checkExistenceOrCreateDir(arguments[OUTPUT_ASS_FILE], "output ass folder")
        helper.checkExistenceOrCreateDir(arguments[RENDER_DIR], "render dir")

        cmdArgs = helper.buildMayaCommand("MikserActionMarnyRender", arguments, None, env)

        # Execute the command line that will export the ass
        updateCompletion(0)
        helper.execute(cmdArgs, env=env)

        # update the completion
        comp = 0.3
        updateCompletion(comp)

        # kick the ass to render images
        # kick -l /s/apps/arnold/mArny2.27.21/shaders ./RE-sq14sh20-all_z-v002.1019.ass -dcau -log -v 2
        # au lieu de
        # kick -nstdin -dp -i /tmp/assfiles/RE-sq14sh20-all_z-v002.1019.ass
        start = int(arguments[START])
        end = int(arguments[END]) + 1
        for frameInt in range(start, end):
            argList = [env["ARNOLD_LOCATION"] + "/bin/kick"]
            frameStr = str(frameInt).rjust(int(arguments[PADDING]), "0")
            # add the arguments to the kick command line
            argList += ["-l", env["ARNOLD_LOCATION"] + "/shaders"]
            assFilePath = arguments[OUTPUT_ASS_FILE] + "/" + arguments[OUTPUT_IMAGE] + "." + frameStr + ".ass"
            if assFilePath.find(" ") != -1:
                assFilePath = "\"" + assFilePath + "\""
            argList += [assFilePath]
            argList += ["-dcau"]
            argList += ["-log"]
            argList += ["-%s" % VERBOSE_LEVEL, "2"]
            # kick the command
            print "\nKicking command : " + " ".join(argList)
            kickOut = subprocess.Popen(argList, close_fds=True, env=env)
            kickOut.communicate()
            # check the file
            filename = arguments[RENDER_DIR] + "/" + arguments[OUTPUT_IMAGE] + "." + frameStr + "." + str(arguments[FORMAT])
            print "Checking \"%s\"..." % filename
            if not os.path.exists(filename):
                raise Exception
            print "OK."
            # update completion
            comp += 0.7 / (end - start)
            updateCompletion(comp)
        updateCompletion(1)
        print "\nrender done."
    def execute(self, arguments, updateCompletion, updateMessage):
        # init the helper
        helper = PuliActionHelper()
        # convert the paths
        
        prodPath = helper.mapPath(arguments[PROD])
        arguments[OUTPUT_ASS_FILE] = helper.mapPath(arguments[OUTPUT_ASS_FILE])
        arguments[RENDER_DIR] = helper.mapPath(arguments[RENDER_DIR])
        arguments[SCENE] = helper.mapPath(arguments[SCENE])
        projPath = os.path.dirname(arguments[SCENE].split('scenes')[0])

        cameras = arguments["cam"].split(',')

        # init log
        helper.printStartLog("mtoa_sa runner", "v0.0")

        # check existence of output ass folders
        helper.checkExistenceOrCreateDir(arguments[OUTPUT_ASS_FILE], "output ass folder")
        helper.checkExistenceOrCreateDir(arguments[RENDER_DIR], "render dir")
        
        env = helper.getEnv(am_version=arguments[ARNOLD_VERSION],
                            maya_version=arguments[MAYA_VERSION],
                            shave_version=arguments[SHAVE_VERSION],
                            crowd_version=arguments[CROWD_VERSION],
                            home=os.environ["HOME"],
                            job=os.path.basename(prodPath),
                            jobdrive=os.path.dirname(prodPath),
                            applis=helper.mapPath("/s/apps/lin"),
                            use_shave=0)
        #
        print "Forcing custom mtoa variables"
        env['ARNOLD_LOCATION'] = '/s/apps/lin/arnold/mtoa0.22.0'
        self.setSolidAngleEnv(env, 'AM_DRIVE', env["ARNOLD_LOCATION"])
        self.setSolidAngleEnv(env, 'MAYA_MODULE_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"])
        self.setSolidAngleEnv(env, 'PYTHONPATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/scripts')
        self.setSolidAngleEnv(env, 'MAYA_PRESET_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/presets')
        self.setSolidAngleEnv(env, 'XBMLANGPATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/icons/%B')
        self.setSolidAngleEnv(env, 'MAYA_PLUG_IN_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/plug-ins')
        self.setSolidAngleEnv(env, 'LD_LIBRARY_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/lib')
        self.setSolidAngleEnv(env, 'ARNOLD_PLUGIN_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/shaders')
        self.setSolidAngleEnv(env, 'MAYA_RENDER_DESC', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"])
        self.setSolidAngleEnv(env, 'PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/bin')
        self.setSolidAngleEnv(env, 'MAYA_SCRIPT_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/scripts/mtoa/2013/mel')
        self.setSolidAngleEnv(env, 'MAYA_SCRIPT_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/scripts')
        self.setSolidAngleEnv(env, 'MAYA_PLUG_IN_RESOURCE_PATH', env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + '/resources')
        self.setSolidAngleEnv(env, 'ARNOLD_LICENSE_PORT', '5053')
        self.setSolidAngleEnv(env, 'ARNOLD_LICENSE_HOST', 'jacket')

        print "################################################"
        print "     ASS EXPORT:",  int(arguments.get(GENERATE_ASS_FILE, '1'))
        print "     KICK:",  int(arguments.get(LAUNCH_KICK, '1'))
        print "################################################"
        if int(arguments.get(GENERATE_ASS_FILE, '1')):
        #if exportTest:
            #+/+Mikanada+/+
            cmdArgs = helper.buildMayaCommand("MikserActionMtoA_SARender", arguments, [projPath, arguments[SCENE]], env)
            # Execute the command line that will export the ass
            print '\nLaunch export command "%s"' % cmdArgs
            comp = 0
            updateCompletion(comp)
            startTime = time.time()
            ret = helper.execute(cmdArgs, env=env)
            print '===================================================='
            print '  MikserActionMtoA_SARender returns with code %d' % (ret)
            print '  Process took %s s' %str(time.time() - startTime).split('.')[0]
            print '===================================================='
            #
            #    mtoa exits with an error code.... Arrrrhhh
            #
            if ret != 0:
                print 'Warning, maya has been quit with an error code'

        # Extra kick flags
        extraKickFlags = []
        if EXTRA_KICK_FLAGS in arguments.keys():
            extraKickFlags = self.parseExtraKickArgs(arguments[EXTRA_KICK_FLAGS])

        # kick the ass to render images
        # kick -l /s/apps/arnold/mArny2.27.21/shaders ./RE-sq14sh20-all_z-v002.1019.ass -dcau -log -v 2
        # au lieu de
        # kick -nstdin -dp -i /datas/tmp/assfiles/RE-sq14sh20-all_z-v002.1019.ass
        start = int(arguments[START])
        end = int(arguments[END])
        totalFrames = end - start + 1
        
        frameCompletionPattern = re.compile("\| (.*)% done .* rays/pixel")


        argList = [ env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + "/bin/kick"]
        argList += ["-l", env["ARNOLD_LOCATION"] + '/' + env["MAYA_VERSION"] + "/shaders"]
        argList += ["-nokeypress"]
        argList += ["-dp"]
        argList += ["-dw"]
        argList += ["-log"]
        # no license check
        if NO_LIC_CHECK in arguments.keys():
            if int(arguments[NO_LIC_CHECK]):
                argList += ["-sl"]
        # verbose level
        if VERBOSE_LEVEL in arguments.keys():
            argList += ["-v", str(arguments[VERBOSE_LEVEL])]
        # number of threads
        if NUMBER_OF_THREADS in arguments.keys():
            argList += ["-t", str(arguments[NUMBER_OF_THREADS])]
        # anti-aliasing samples
        if ANTI_ALIASING_SAMPLES in arguments.keys():
            argList += ["-as", str(arguments[ANTI_ALIASING_SAMPLES])]
        # Extra kick flags
        argList += extraKickFlags
        
        for frameInt in range(start, end + 1):
            frameStr = str(frameInt).rjust(int(arguments[PADDING]), "0")
            # add the arguments to the kick command line
            assFilePath = arguments[OUTPUT_ASS_FILE] + "/" + arguments[OUTPUT_IMAGE] + "." + frameStr + ".ass"
            # support for compress ass
            if COMPRESS_ASS in arguments.keys():
                if int(arguments[COMPRESS_ASS]):
                    assFilePath += ".gz"
            if assFilePath.find(" ") != -1:
                assFilePath = "\"" + assFilePath + "\""
                
            cmdList = argList[:]
            cmdList.append(assFilePath)

            # kick the command
            print "\nKicking command : " + " ".join(cmdList)

            os.umask(2)
            out = subprocess.Popen(cmdList, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, env=env)
            rc = None
            while rc is None:
                line = out.stdout.readline()
                if not line:
                    break
                print line,
                sys.stdout.flush()
                fcp = frameCompletionPattern.search(line)
                if fcp:
                    framecomp = float(fcp.group(1).strip())
                    fc = float(framecomp / 100) / float(totalFrames)
                    updateCompletion(comp + fc)
                rc = out.poll()

            out.communicate()
            rc = out.poll()
            print '===================================================='
            print '  kick command returns with code %d' % rc
            print '===================================================='
            if rc != 0:
                print '  Kick command failed...'
                raise Exception('  Kick command failed...')
            comp += 1.0 / float(totalFrames)

            # suppression of ass files
            if not int(arguments[LEAVE_ASS_FILES]):
                try:
                    os.remove(assFilePath)
                except OSError:
                    print "\nFailed to remove '" + assFilePath + "'\n"
            else:
                print "\nLeaving Ass file on disk : '" + assFilePath + "'\n"

            self.invertedFormatsMap = {'1': 'jpg',  '2': 'tif', '3': 'exr', '4': 'png'}
            filename = arguments[RENDER_DIR] + "/" + arguments[OUTPUT_IMAGE] + "." + frameStr + "." + self.invertedFormatsMap[str(arguments[FORMAT])]

            # Check file existence
            filename = filename.rstrip()
            print "> %s" % filename
            if not os.path.exists(filename):
                raise Exception("file does not exist!")
            print "  OK."

            # exrmakescanlined
            make_scanlined = 1
            if MAKE_SCANLINED in arguments and os.path.splitext(filename)[1][1:] == 'exr':
                print "  Make exr scanlined..."
                exrscanlinedCmdArgs = ["/s/apps/lin/bin/exrmakescanlined-test"]
                exrscanlinedCmdArgs.append("-c")
                exrscanlinedCmdArgs.append(filename)
                tf = tempfile.NamedTemporaryFile(prefix='/tmp/')
                dest = tf.name
                tf.close()
                exrscanlinedCmdArgs.append(dest)
                subp = subprocess.Popen(exrscanlinedCmdArgs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                output, error = subp.communicate()
                if subp.returncode == 0:
                    # idiff comparison
                    idiffcmd = ["/s/apps/lin/bin/idiff-1.1.7"]
                    idiffcmd.append(filename)
                    idiffcmd.append(dest)
                    devnull = open('/dev/null', 'w')
                    idiffret = subprocess.Popen(idiffcmd, env=os.environ, stdout=devnull).wait()
                    if True:
                        print "       idiff : tiled and scanlined images match, replacing the tiled version..."
                        shutil.move(dest, filename+".tmp")
                        os.rename(filename+".tmp", filename)
                        print "       tiled version overwritten"
                    else :
                        print "       idiff : Keeping Tiled version : images do not match !!!"
                    # FIXME check permissions
                    import stat
                    st = os.stat(filename)
                    if not bool(st.st_mode & stat.S_IRGRP) or not bool(st.st_mode & stat.S_IWGRP):
                        logtemp = open("/s/apps/lin/puli/tmplog.csv", 'a')
                        import socket
                        logtemp.write("%s\t%s\t%s\tmtoa\t%s\t%s\n" % (filename, socket.gethostname(), os.path.basename(prodPath), oct(stat.S_IMODE(st.st_mode)), time.strftime('%H:%M', time.localtime())))
                        logtemp.close()
                elif subp.returncode == 1:
                    print "    Nothing to do."
                elif error:
                    print error
                else:
                    print "an error has occured, keeping the tiled version"

        updateCompletion(1)
        print "\nrender done."