Пример #1
0
def createProject():
    
    site = 'https://chimneypot.shotgunstudio.com'    
    scriptName = 'createProject'
    scriptKey = '90699580e396b61d3acfb71e0595adde7458dfd4'    
    
    repo = '/mnt/karramba/'    
        
    rootList = ['film', 'out', 'ref', 'src', 'temp']
    filmList = ['assets', 'sequences']    
    assetList = ['light', 'material', 'mattepaint', 'model', 'rig', 'shader', 'textures']
    shotList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'src', 'tmp']
    sqList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'shots']
    dataList = ['cache', 'geo', 'render', 'shadowmap', 'sim', 'track', 'photonmap']
    outList = ['dailies', 'hires']

    prName = raw_input('Print project name:')
    
    prPath = repo + prName     
    
    if not os.path.exists(prPath):
        os.mkdir(prPath)
        for i in rootList:
            os.makedirs(prPath + os.sep + i)
        for i in filmList:
            os.makedirs(prPath + os.sep + 'film' + os.sep + i)    
        for i in assetList:
            os.makedirs(prPath + os.sep + 'film' + os.sep + 'assets' + os.sep + i)
        for i in outList:
            os.makedirs(prPath + os.sep + 'out' + os.sep + i)

    sg = Shotgun(site, scriptName, scriptKey)
    sg.create('Project', {'name':prName})    
Пример #2
0
def getProjects():
	
	site = 'https://chimneypot.shotgunstudio.com'	
	scriptName = 'AssetBrowser'
	scriptKey = 'c35ab5f5322d4b1e8b6488bb315c03e5f38881ea'	
	
	repo = '/mnt/karramba/'	
		
	rootList = ['film', 'out', 'ref', 'src', 'temp']
	filmList = ['assets', 'sequences']	
	assetList = ['light', 'material', 'mattepaint', 'model', 'rig', 'shader', 'textures']
	shotList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'src', 'tmp']
	sqList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'shots']
	dataList = ['cache', 'geo', 'render', 'shadowmap', 'sim', 'track', 'photonmap']
	outList = ['dailies', 'hires']

	prName = raw_input('Print project name:')
	
	prPath = repo + prName 	
	
	if not os.path.exists(prPath):
		os.mkdir(prPath)
		for i in rootList:
			os.makedirs(prPath + os.sep + i)
		for i in filmList:
			os.makedirs(prPath + os.sep + 'film' + os.sep + i)	
		for i in assetList:
			os.makedirs(prPath + os.sep + 'film' + os.sep + 'assets' + os.sep + i)
		for i in outList:
			os.makedirs(prPath + os.sep + 'out' + os.sep + i)

	sg = Shotgun(site, scriptName, scriptKey)
	sg.create('Project', {'name':prName})
Пример #3
0
def submitShotgunTicket(output, jobList):

	currentuser = str(User.currentUser().name())
	title = "AtS - %s"%currentuser

	desc = []
	desc.append(output+"\n")
	desc.append("JOBLIST:") 

	for job in jobList:
	    desc.append(str(job.key())+" - "+str(job.name())) 
			
	sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
	
        id = sg.find("HumanUser",[['login','is',currentuser]],['id'])
        userid = id[0]

        ticket_data = {
            'created_by': {'type':'HumanUser','id':userid['id']},
            'title': title,
            'description': "\n".join(desc),
            'addressings_to':[{'type':'Group', 'id':19}, {'type':'HumanUser','id':userid['id']}],
            'project': {'type':'Project', 'id':178},
            'sg_service': {'type':'CustomNonProjectEntity01', 'id':27},
        }
        sg_ticket = sg.create('Ticket', ticket_data, ['id'])
        new_ticket_url = SERVER_PATH + "/detail/Ticket/" + str(sg_ticket['id'])
        QDesktopServices.openUrl( QUrl(new_ticket_url) )
Пример #4
0
    def _moveFilesToPublish(self):
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'playBlastPublisher'
        api_key     = '718daf67bfd2c7e974f24e7cbd55b86bb101c4e5618e6d5468bc4145840e4558'

        sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        selectedShots = [item.text(0) for item in self.treeWidgetItems if item.checkState(0)]
        if selectedShots:
            for each in selectedShots:
                episode = each.split('sh')[0]
                shotName = '%s_sh%s' % (each.split('sh')[0], each.split('sh')[1].split('Lay')[0])
                self.publishPath = self.publishingPath(episode, shotName)
                for root, dirs, files in os.walk(self.shFldPath):
                    for fl in sorted(files):
                        if fl.endswith('.mov') and fl == '%s.mov' % each:
                            srcPath = os.path.join(root,fl)
                            self.playblastName = fl
                            while os.path.exists(os.path.join(self.publishPath, fl)):
                                allFiles= os.listdir(self.publishPath)
                                publishFiles = []
                                if allFiles:
                                    for allFile in allFiles:
                                        if allFile.endswith('.mov'):
                                            publishFiles.append(allFile)
                                versionNumber = int(sorted(publishFiles)[-1].split('.v')[1].split('.mov')[0])
                                versionNumber += 1
                                if versionNumber < 10:
                                    publishFileName = '%sLayout.v%03d.mov' % (shotName.replace('_', ''), versionNumber)
                                    self.publishPath = os.path.join(self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(self.publishPath)
                                else:
                                    publishFileName = '%sLayout.v%02d.mov' % (shotName.replace('_', ''), versionNumber)
                                    self.publishPath = os.path.join(self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(self.publishPath)

                            shutil.copy2(srcPath, self.publishPath)
                            publishMovPath = os.path.join(self.publishingPath(episode, shotName), self.playblastName)
                            getShotTasks =  sgsrv.find_one('Shot',  filters = [["code", "is", shotName]], fields=['id', 'tasks'])

                            for key, values in getShotTasks.iteritems():
                                if key == 'tasks':
                                    for value in values:
                                        if value['name'] == 'Layout':
                                            self.taskId = value['id']
                            if self.publishPath.endswith('review'):
                                self.publishPath = os.path.join(self.publishPath,fl)
                                self.playblastName = fl
                            data = { 'project': {'type':'Project','id': 66},
                                     'code':  self.playblastName,
                                     'description': 'Layout playblast published',
                                     'sg_path_to_movie': publishMovPath,
                                     'sg_status_list': 'rev',
                                     'entity': {'type':'Shot', 'id':getShotTasks['id']},
                                     'sg_task': {'type':'Task', 'id':self.taskId},
                                     'user': {'type':'HumanUser', 'id':92} }
                            result = sgsrv.create('Version', data)
                            result2 = sgsrv.upload("Version", result['id'], publishMovPath, "sg_uploaded_movie")
                print "Done"
    def _pubBttn(self):
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'playBlastPublisher'
        api_key     = '718daf67bfd2c7e974f24e7cbd55b86bb101c4e5618e6d5468bc4145840e4558'

        sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)

        selectedShots = sorted([item.text(0) for item in self.shotTreeWidgetItems if item.checkState(0)])
        for shot in selectedShots:
            if shot in self.srcPath.keys():
                destPath = self._getPublishPath(shot)
                srcPath = self.srcPath[str(shot)]
                ext = os.path.splitext(srcPath)[-1]
#                 print os.path.basename(srcPath)
#                 while os.path.exists(os.path.join(str(destPath), os.path.basename(srcPath))):
#                     print "In Loop"
#                     print os.path.basename(srcPath)
#                     allFiles= os.listdir(destPath)
#                     publishFiles = []
#                     if allFiles:
#                         for allFile in allFiles:
#                             if allFile.endswith(ext):
#                                 print allFile
#                                 publishFiles.append(allFile)
#                     versionNumber = int(sorted(publishFiles)[-1].split('.v')[1].split(ext)[0])
#                     versionNumber += 1
#                     if versionNumber < 10:
#                         publishFileName = '%sLayout.v%03d%s' % (shotName.replace('_', ''), versionNumber, ext)
#                         self.publishPath = os.path.join(self.publishPath, publishFileName)
#                         self.playblastName = os.path.basename(self.publishPath)
#                     else:
#                         publishFileName = '%sLayout.v%02d%s' % (shotName.replace('_', ''), versionNumber, ext)
#                         self.publishPath = os.path.join(self.publishPath, publishFileName)
#                         self.playblastName = os.path.basename(self.publishPath)
#                 shutil.copy2(srcPath, destPath)

                shotName = '%s_%s' % (self._getEpisodeName(shot), self._getShotName(shot))
                getShotTasks =  self.tk.shotgun.find_one('Shot',  filters = [["code", "is", shotName]], fields=['id', 'tasks'])
                taskName = self.comboBox.currentText()
                self.playblastName = os.path.basename(srcPath)
                publishMovPath = os.path.join(destPath, self.playblastName).replace('\\', '/')
                shutil.copy2(srcPath, destPath)
                for task in getShotTasks['tasks']:
                    if task['name'] == taskName:
                        taskId = task['id']
                        data = { 'project': {'type':'Project','id': 66},
                             'code':  self.playblastName,
                             'description': 'Playblast published',
                             'sg_path_to_movie': publishMovPath,
                             'sg_status_list': 'rev',
                             'entity': {'type':'Shot', 'id':getShotTasks['id']},
                             'sg_task': {'type':'Task', 'id':taskId},
                             'user': {'type':'HumanUser', 'id':92} }
                        result = sgsrv.create('Version', data)
                        result2 = sgsrv.upload("Version", result['id'], publishMovPath, "sg_uploaded_movie")
                        print "Published %s" % self.playblastName
    def _pubBttn(self):
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'playBlastPublisher'
        api_key     = '718daf67bfd2c7e974f24e7cbd55b86bb101c4e5618e6d5468bc4145840e4558'

        sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)

        selectedShots = sorted([item.text(0) for item in self.shotTreeWidgetItems if item.checkState(0)])
        for shot in selectedShots:
            if shot in self.srcPath.keys():
                destPath = self._getPublishPath(shot)
                srcPath = self.srcPath[str(shot)]
                ext = os.path.splitext(srcPath)[-1]
#                 print os.path.basename(srcPath)
#                 while os.path.exists(os.path.join(str(destPath), os.path.basename(srcPath))):
#                     print "In Loop"
#                     print os.path.basename(srcPath)
#                     allFiles= os.listdir(destPath)
#                     publishFiles = []
#                     if allFiles:
#                         for allFile in allFiles:
#                             if allFile.endswith(ext):
#                                 print allFile
#                                 publishFiles.append(allFile)
#                     versionNumber = int(sorted(publishFiles)[-1].split('.v')[1].split(ext)[0])
#                     versionNumber += 1
#                     if versionNumber < 10:
#                         publishFileName = '%sLayout.v%03d%s' % (shotName.replace('_', ''), versionNumber, ext)
#                         self.publishPath = os.path.join(self.publishPath, publishFileName)
#                         self.playblastName = os.path.basename(self.publishPath)
#                     else:
#                         publishFileName = '%sLayout.v%02d%s' % (shotName.replace('_', ''), versionNumber, ext)
#                         self.publishPath = os.path.join(self.publishPath, publishFileName)
#                         self.playblastName = os.path.basename(self.publishPath)
#                 shutil.copy2(srcPath, destPath)

                shotName = '%s_%s' % (self._getEpisodeName(shot), self._getShotName(shot))
                getShotTasks =  self.tk.shotgun.find_one('Shot',  filters = [["code", "is", shotName]], fields=['id', 'tasks'])
                taskName = self.comboBox.currentText()
                self.playblastName = os.path.basename(srcPath)
                publishMovPath = os.path.join(destPath, self.playblastName).replace('\\', '/')
                shutil.copy2(srcPath, destPath)
                for task in getShotTasks['tasks']:
                    if task['name'] == taskName:
                        taskId = task['id']
                        data = { 'project': {'type':'Project','id': 66},
                             'code':  self.playblastName,
                             'description': 'Playblast published',
                             'sg_path_to_movie': publishMovPath,
                             'sg_status_list': 'rev',
                             'entity': {'type':'Shot', 'id':getShotTasks['id']},
                             'sg_task': {'type':'Task', 'id':taskId},
                             'user': {'type':'HumanUser', 'id':92} }
                        result = sgsrv.create('Version', data)
                        result2 = sgsrv.upload("Version", result['id'], publishMovPath, "sg_uploaded_movie")
                        print "Published %s" % self.playblastName
Пример #7
0
def getProjects():

    site = 'https://chimneypot.shotgunstudio.com'
    scriptName = 'AssetBrowser'
    scriptKey = 'c35ab5f5322d4b1e8b6488bb315c03e5f38881ea'

    repo = '/mnt/karramba/'

    rootList = ['film', 'out', 'ref', 'src', 'temp']
    filmList = ['assets', 'sequences']
    assetList = [
        'light', 'material', 'mattepaint', 'model', 'rig', 'shader', 'textures'
    ]
    shotList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'src', 'tmp']
    sqList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'shots']
    dataList = [
        'cache', 'geo', 'render', 'shadowmap', 'sim', 'track', 'photonmap'
    ]
    outList = ['dailies', 'hires']

    prName = raw_input('Print project name:')

    prPath = repo + prName

    if not os.path.exists(prPath):
        os.mkdir(prPath)
        for i in rootList:
            os.makedirs(prPath + os.sep + i)
        for i in filmList:
            os.makedirs(prPath + os.sep + 'film' + os.sep + i)
        for i in assetList:
            os.makedirs(prPath + os.sep + 'film' + os.sep + 'assets' + os.sep +
                        i)
        for i in outList:
            os.makedirs(prPath + os.sep + 'out' + os.sep + i)

    sg = Shotgun(site, scriptName, scriptKey)
    sg.create('Project', {'name': prName})
Пример #8
0
def submitShotgunTicket(output, jobList):

    currentuser = str(User.currentUser().name())
    title = "AtS - %s" % currentuser

    desc = []
    desc.append(output + "\n")
    desc.append("JOBLIST:")

    for job in jobList:
        desc.append(str(job.key()) + " - " + str(job.name()))

    sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

    id = sg.find("HumanUser", [['login', 'is', currentuser]], ['id'])
    userid = id[0]

    ticket_data = {
        'created_by': {
            'type': 'HumanUser',
            'id': userid['id']
        },
        'title':
        title,
        'description':
        "\n".join(desc),
        'addressings_to': [{
            'type': 'Group',
            'id': 19
        }, {
            'type': 'HumanUser',
            'id': userid['id']
        }],
        'project': {
            'type': 'Project',
            'id': 178
        },
        'sg_service': {
            'type': 'CustomNonProjectEntity01',
            'id': 27
        },
    }
    sg_ticket = sg.create('Ticket', ticket_data, ['id'])
    new_ticket_url = SERVER_PATH + "/detail/Ticket/" + str(sg_ticket['id'])
    QDesktopServices.openUrl(QUrl(new_ticket_url))
Пример #9
0
M.login('*****@*****.**', 'PASSWORD')
M.select("eng-support") # mailbox/tag name
typ, data = M.search(None, 'ALL')
for num in data[0].split():
    typ, msgdata = M.fetch(num, '(RFC822)')
    #print 'Message %s\n%s\n' % (num, data[0][1])
    msg_dict = parse.parse(msgdata[0][1])
    print "message from %s" % msg_dict["from"]

    people = sg.find("HumanUser",[['email','is',msg_dict["from"]]],['id','name'])
    if len(people) < 1:
        print "couldn't find user"
    else:
        # if we find a valid user, create a ticket for them
        user = people[0]
        ticket_data = {
            'created_by': {'type':'HumanUser','id':user['id']},
            'addressings_to': [{'type':'Group','id':5}],
            'title': msg_dict['subject'],
            'description': msg_dict['body'],
            'project': {'type':'Project', 'id':178},
        }
        sg.create('Ticket', ticket_data, return_fields=['id'])

        # if we made it this far the e-mail was processed, now delete it
        M.store(num, '+FLAGS', '\\Deleted')

M.close()
M.logout()

__author__ = 'andrew.willis'

from shotgun_api3 import Shotgun

sg = Shotgun("http://andrewwillish.shotgunstudio.com", "scriptTest", "8b7db88321b7c296541580d1659872d2e63527c040b37b4a2ca0eb47f9da04cb")
proj = sg.find_one("Project",[['name','is','KIKO']])
print sg.create("shot",{'code':'SEQ01','project':proj})
#sg.update('Shot',shot['id'],{"sg_status_list":"ip"})
#sg.delete("Shot", 1160)
Пример #11
0
class studioShotgun(object):
    def __init__(self, path, name, key, project):
        self.SERVER_PATH = path
        self.SCRIPT_NAME = name     
        self.SCRIPT_KEY = key
        self.project_id = project
        self.sg = Shotgun(self.SERVER_PATH, self.SCRIPT_NAME, self.SCRIPT_KEY)

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectId(self, newId):
        self.project_id = newId

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectName(self, name):
        newId = 0
        projects = self.sg.find('Project', [], ['name'])
        for project in projects:
            if project['name'] == name:
                newId = project['id']

        self.project_id = newId

    #----------------------------------------------------------------------
    ## find asset by name
    def findAssetByName(self, name):
        fields = ['id', 'code', 'sg_asset_type', 'tasks']
        filters = [['project', 'is', {'type': 'Project', 'id': self.project_id}], ['code', 'is', name]]
        
        result = self.sg.find('Asset', filters, fields)
    
        return result
    
    #----------------------------------------------------------------------
    ## find shot by name
    def findShotByName(self, episode, shot):
        fields = ['id', 'code', 'sg_asset_type', 'tasks', 'sg_sequence']
        filters = [['project', 'is', {'type': 'Project', 'id': self.project_id}], ['code', 'is', shot]]
        
        result = self.sg.find('Shot', filters, fields)
    
        for x in result:
            name = x['sg_sequence']['name'].split('_')[0]
            if name == episode:
                return x
    
        return []

    #----------------------------------------------------------------------
    ## upload thumbnail to asset
    def uploadThumbnail(self, asset, thumbnail):
        upload = 0
        asset = self.findAssetByName(asset)
        if asset:
            upload = self.sg.upload_thumbnail("Asset", asset[0]['id'], thumbnail)
    
        return upload

    #----------------------------------------------------------------------
    ## create new asset
    def createAsset(self, asset, assetType, template, assetFile='', description=''):
        ## find asset
        asset = self.findAssetByName(asset)
        
        if not asset:
            ## create asset + task template
            filters = [['code', 'is', template]]
            template = self.sg.find_one('TaskTemplate', filters)
            
            data = {'project': {'type': 'Project', 'id': self.project_id}, 
                    'code': asset,
                    'description': description, 
                    'sg_asset_type': assetType, 
                    'sg_url_perforce': assetFile, 
                    'task_template': template}
    
            asset = self.sg.create('Asset', data)
    
        return asset

    #----------------------------------------------------------------------
    ## update file path in asset
    def updateAssetFilePath(self, asset, filename):
        asset = self.findAssetByName(asset)
    
        data = {'sg_url_perforce': filename}
        asset = self.sg.update("Asset", asset[0]['id'], data)
    
        return asset

    #----------------------------------------------------------------------
    ## create new version
    def createVersion(self, shotId, taskId, userId, filename, comment=''):
        curTime = datetime.now().strftime('%Y.%m.%d_%H.%M')
        fname = str(filename.split('/')[-1].split('.')[0]) + '_' + curTime
    
        data = {'project': {'type': 'Project', 'id': self.project_id},
                'code': fname,
                'description': comment,
                'sg_status_list': 'rev',
                'entity': {'type': 'Shot', 'id': shotId},
                'sg_task': {'type': 'Task', 'id': taskId},
                'user': {'type': 'HumanUser', 'id': userId}}
        
        result = self.sg.create('Version', data)
        
        upload = self.sg.upload('Version', result['id'], filename, 'sg_uploaded_movie')
    
        return [result, upload]

    #----------------------------------------------------------------------
    ## get user data from shotgum
    def getUserData(self, user):
        filters = [['login', 'is', user]]
        user = self.sg.find('HumanUser', filters)

        if user:
            return user[0]
        else:
            return []

    #----------------------------------------------------------------------
    ## get all user from project
    def getAllUsers(self):
        fields = ['id', 'login', 'name', 'projects', 'department']
        filters = [['projects', 'is', {'type': 'Project', 'id': self.project_id}]]
        users = self.sg.find('HumanUser', filters, fields)
    
        return users
Пример #12
0
    class genericUtils:
        def __init__(self):
            self.sg = Shotgun('https://' + URL, name, API)

        def getFields(self, entity):
            '''get the fields for a type/entity as a list so we can pass it as an arg easily
            this is used all the time to make sure we get all the fields that we may ever need for a type/entity
            '''
            allFields = []
            fields = self.sg.schema_field_read(entity)
            for field in fields:
                allFields.append(field)
            return allFields

        def project(self, project):
            '''Gets the Shotgun project name and ID
            '''
            retFields = self.getFields('Project')
            project = project.replace('_', ' ')
            return self.sg.find_one("Project", [["name", "is", project]],
                                    retFields)

        def sequence(self, project, sequence):
            '''Returns the shotgun sequence name and ID 
            Parameters : (project, sequence)
            '''
            retFields = self.getFields('Sequence')
            return self.sg.find_one(
                "Sequence",
                [["code", "is", sequence], ['project', 'is', project]],
                retFields)

        def shot(self, project, shot):
            '''Returns the shotgun shot name and ID 
            Parameters : (project, shot)
            '''
            retFields = self.getFields('Shot')
            return self.sg.find_one(
                'Shot', [['code', 'is', shot], ['project', 'is', project]],
                retFields)

        def createProject(self, project):
            '''Creates a project in Shotgun given a project name
            Parameters : (project)
            '''
            filters = [['code', 'is', 'a']]
            template = self.sg.find_one('Project', [['name', 'is', 'a']],
                                        ['layout_project', 'id'])
            data = {'name': project, 'layout_project': template}
            return self.sg.create('Project', data)

        def createSequence(self, project, sequence):
            '''Creates a sequence in shotgun given 
            Parameters : (project, sequence)
            '''
            data = {
                'project': {
                    "type": "Project",
                    "id": project['id']
                },
                'code': sequence
            }
            return self.sg.create('Sequence', data)

        def createShot(self, project, shot, seq='', taskTemplateName=''):
            '''Creates a sequence in shotgun given 
            Parameters : (project, shot, seq='', taskTemplateName='Basic shot template'
            '''
            filters = [['code', 'is', taskTemplateName]]
            template = self.sg.find_one('TaskTemplate', filters)

            data = {
                'project': {
                    "type": "Project",
                    "id": project['id']
                },
                'code': shot,
                'task_template': template,
                'description': '',
                'self.sg_sequence': seq,
                'self.sg_status_list': 'wtg'
            }
            result = self.sg.create('Shot', data)
            return result

        def notesFind(self, shotID):
            '''Find all notes on a shot 
            Parameters : (shotID)
            Output : Note data :
            ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
            addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
            'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
            'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
            '''
            note = self.sg.find('Note', [['note_links', 'is', shotID]],
                                ['subject', 'content', 'created_at'],
                                [{
                                    'field_name': 'created_at',
                                    'direction': 'desc'
                                }])
            return note

        def notesFindLatest(self, shotID):
            '''Find the latest note on a shot
            Parameters : (shotID)
            Call with notesFindLatest(shot)['content'] for the note content only
            Output : Note data:
            ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
            addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
            'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
            'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
            '''
            note = self.notesFind(shotID)[0]
            return note

        def notesCreate(self, project, shotID, subject, content):
            '''Create a note for a shot given
            Parameters : (project, shotID, subject, content)
            Output : noteID
            '''
            # enter data here for a note to create
            data = {
                'subject': subject,
                'content': content,
                'note_links': [shotID],
                'project': project
            }
            # create the note
            noteID = self.sg.create('Note', data)
            return noteID

        def versionCreate(self,
                          project,
                          shot,
                          verName,
                          description,
                          framePath,
                          firstFrame,
                          lastFrame,
                          clientName=None,
                          sourceFile=None,
                          task=None,
                          user=None,
                          final=False,
                          makeThumb=False,
                          makeThumbShot=False):
            '''Create a version
            Parameters : (project, shotID, verName, description, framePath, firstFrame, lastFrame, clientName=None, sourceFile=None, task=None)
            Output : versionID
            '''

            data = {
                'project': project,
                'code': verName,
                'description': description,
                'sg_path_to_frames': framePath,
                #'sg_frame_range': str(firstFrame) + '-' + str(lastFrame),
                'sg_first_frame': int(firstFrame),
                'sg_last_frame': int(lastFrame),
                'sg_status_list': 'rev',
                'entity': shot
            }
            #if user != None:
            #data['user']
            if task != None:
                filters = [['content', 'is', task], ['entity', 'is', shot]]
                taskID = self.sg.find_one('Task', filters)
                data['sg_task'] = taskID
            #if final == True and 'send
            # in case we're putting a client version in here we need this code.
            # we are expecting a field called self.sg_client_name in the version table.
            # please make sure you create this in the shotgun setup
            # read the schema and if the client_name is not found, create it.
            '''
            versionFields = self.sg.schema_field_read('Version')
            if 'sg_client_name' not in versionFields and clientName != None:
                newField = self.sg.schema_field_create('Version','text','Client Name')
            if clientName != None :
                data['sg_client_name'] =  clientName
        
            #'user': {'type':'HumanUser', 'id':165} }
            # here we need to create a field for storing the source file that created this version.
            # if it's not there, create the field, and if it's there just update it.
            
            if 'sg_source_file' not in versionFields and sourceFile != None:
                newField = self.sg.schema_field_create('Version','text','Source File')
            if sourceFile != None:
                data['sg_source_file'] = sourceFile
            '''

            versionData = self.sg.create('Version', data)
            # handle the thumbnail grabbing here
            middleFrame = (int(firstFrame) + int(lastFrame)) / 2
            padding, padString = fxpipe.framePad(framePath)
            paddedFrame = padString % (middleFrame)
            if makeThumb == True:
                thumbData = self.sg.upload_thumbnail(
                    'Version', versionData['id'],
                    framePath.replace(padding, paddedFrame))
            if makeThumbShot == True:
                thumbData = self.sg.upload_thumbnail(
                    'Shot', shot['id'],
                    framePath.replace(padding, paddedFrame))
            return versionData

        #add a task version to the system
        def versionCreateTask(self,
                              project,
                              shot,
                              verName,
                              description,
                              framePath,
                              firstFrame,
                              lastFrame,
                              task,
                              sourceFile=''):
            '''
            DEPRECATED : USE versionCreate instead with the task='TASKNAME'
            Parameters : (project, shot, verName, description, framePath, firstFrame, lastFrame, task, sourceFile = '')
            Output : Version ID
            '''
            filters = [['content', 'is', task], ['entity', 'is', shot]]
            taskID = self.sg.find_one('Task', filters)
            data = {
                'project': project,
                'code': verName,
                'description': description,
                'self.sg_path_to_frames': framePath,
                'frame_range': str(firstFrame) + '-' + str(lastFrame),
                'self.sg_first_frame': firstFrame,
                'self.sg_last_frame': lastFrame,
                #'self.sg_uploaded_movie': '/Users/throb/Downloads/test.m4v',
                #'self.sg_first_frame': 1,
                #'self.sg_last_frame': 100,
                'self.sg_status_list': 'rev',
                'self.sg_task': taskID,
                'entity': shot
            }
            # here we need to create a field for storing the source file that created this version.
            # if it's not there, create the field, and if it's there just update it.
            try:
                tmp2 = {}
                tmp2 = tmp['self.sg_source_file']
            except:
                newField = self.sg.schema_field_create('Version', 'text',
                                                       'Source File')
            if sourceFile != '':
                data['self.sg_source_file'] = sourceFile

            return self.sg.create('Version', data)

        # look for specific version
        def versionFind(self, versionID):
            '''Find all versions in a shot with most recent first
            Parameters : (shotID)
            Output : Version data:
            ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
            'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
            'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
            'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
            'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
            'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
            'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
            'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
            '''
            retFields = self.getFields('Version')
            return self.sg.find('Version', [['id', 'is', versionID]],
                                retFields, [{
                                    'field_name': 'created_at',
                                    'direction': 'desc'
                                }])[0]

        # look for versions in a shot:
        def versionFindShot(self, shotID):
            '''Find all versions in a shot with most recent first
            Parameters : (shotID)
            Output : Version data:
            ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
            'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
            'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
            'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
            'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
            'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
            'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
            'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
            '''
            retFields = self.getFields('Version')
            return self.sg.find('Version', [['entity', 'is', shotID]],
                                retFields, [{
                                    'field_name': 'created_at',
                                    'direction': 'desc'
                                }])

        def versionFindLatest(self, shotID):
            '''Find only the most recent version
            Parameters : (shotID)
            Output : Version data:
            ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
            'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
            'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
            'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
            'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
            'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
            'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
            'filmstrip_image', 'tag_list', 'frame_count', 'flagged']         
            '''
            retFields = self.getFields('Version')
            return self.sg.find_one('Version', [['entity', 'is', shotID]],
                                    retFields, [{
                                        'field_name': 'created_at',
                                        'direction': 'desc'
                                    }])

        # search for the latest task given shotID and task info
        def versionFindLatestTask(self, shotID, task):
            retFields = self.getFields('Version')
            # first look for the task and get the ID
            filters = [['content', 'is', task], ['entity', 'is', shotID]]
            taskID = self.sg.find_one('Task', filters)
            # then look for the latest
            #version using the task ID.  note that we need to use the [0] or else we're sending the array versus the hash
            versionLatest = self.sg.find_one(
                'Version',
                [['entity', 'is', shotID], ['self.sg_task', 'is', taskID]],
                retFields, [{
                    'field_name': 'created_at',
                    'direction': 'desc'
                }])
            return versionLatest

        ## The following requires a field called "client_version" be added to shotgun
        def versionClientUpdate(self,
                                shotID,
                                version,
                                clientVersionName='Client Version'):
            '''This takes the shotID and version (int) and updates the shot with this client version number
            Sometimes the client wants to see different version numbers versus the internal ones.  This option allows for it.
            You will need to create a field.  Client Version is what I have used but you can specify what you want here.
            Parameters: (shotID, version, clientVersionName ='Client Version')
            Output : Version data
            '''
            sgFieldName = 'sg_' + clientVersionName.lower().replace(' ', '_')
            data = {sgFieldName: version}
            try:
                result = self.sg.update('Shot', shotID['id'], data)
            except:
                newField = self.sg.schema_field_create('Shot', 'number',
                                                       clientVersionName)
                result = self.sg.update('Shot', shotID['id'], data)
            return result

        def uploadQT(self, entityType, item, path):
            '''Upload a file to shotgun in the 'self.sg_qt' field.
            If you do this for a shot, you will need to add this to a field
            the field should be called 'qt' as shotgun will add the self.sg_ to it
            Shotgun provides the self.sg_qt for versions automatically
            Parameters: (entity,item,path)
            uploadQT ('Version',versionData, '/my/file.mov')
            '''
            # Make sure first letter is capitalized
            entity = entityType.capitalize()

            # upload that mother
            if entity.lower() == 'shot':
                try:
                    result = self.sg.upload(entity, item['id'], path, 'sg_qt')
                except:
                    newField = self.sg.schema_field_create('Shot', 'url', 'QT')
                    result = self.sg.upload(entity, item['id'], path, 'sg_qt')

            elif entity.lower() == 'version':
                result = self.sg.upload(entity, item['id'], path,
                                        'sg_uploaded_movie')
            return result

        def versionClientGet(self, shotID, clientVersion='Client Version'):
            '''Get latest client version number
            Parameters : (hotID, clientVersion='Client Version')
            Output : Version data
            '''
            sgFieldName = 'sg_' + clientVersionName.lower().replace(' ', '_')
            try:
                currentVersion = shotID[sgFieldName]
            except:
                currentVersion = 0
            if currentVersion == None:
                return 0
            return currentVersion

        def playlistFind(self, project, playlistName):
            '''Search for a playlist given a project and name
            Parameters : (project, playlistName)
            Output : playlist data:
            ['code', 'description', 'versions', 'created_at', 'sg_cinesync_session_url', 
            'updated_at', 'created_by', 'project', 'filmstrip_image', 'notes', 'image', 
            'updated_by', 'sg_cinesync_session_key', 'sg_status', 'tag_list', 'id', 
            'sg_date_and_time']        
            '''
            retFields = self.getFields('Playlist')
            return self.sg.find_one(
                'Playlist',
                [['code', 'is', playlistName], ['project', 'is', project]],
                retFields)

        def playlistCreate(self,
                           project,
                           playlistName,
                           playlistDescription=''):
            '''Create a playlist given a playlist name
            Parameters : (project, playlistName, playlistDescription='')
            Output : playlist data
            '''
            data = {
                'project': project,
                'code': playlistName,
                'description': playlistDescription
            }
            return self.sg.create('Playlist', data)

        # Add a version to a playlist
        def playlistAddVersion(self, project, playlistName, version):
            '''
            Description :\n
            This adds a version (existing version in the system) to a playlist.\n
            You need to give it: (in order)\r
            shotgun connection class\r
            project (dict of the project info including name and id)\r
            playlist name (string of the name of the playlist)\r
            version (dict of the version you wish to add\n
            It will return with a dict of the playlist
            '''

            my_playlist_list = self.sg.find_one(
                'Playlist',
                [['code', 'is', playlistName], ['project', 'is', project]],
                ['versions'])
            if len(my_playlist_list):
                ver_list = my_playlist_list['versions']
                ver_list.append({
                    'type': 'Version',
                    'name': version['code'],
                    'id': version['id']
                })
                result = self.sg.update('Playlist', my_playlist_list['id'],
                                        {'versions': ver_list})
                return result

        def playlistInfo(self, project, playlistName):
            '''Get playlist info (eg version name and description)
            Parameters : (project, playlistName)
            Output : version data
            '''
            data = []
            versionData = []
            retFields = self.getFields('Version')
            for versionInPlaylist in self.sg.find_one(
                    'Playlist',
                [['code', 'is', playlistName], ['project', 'is', project]],
                ['versions'])['versions']:
                data.append(
                    self.sg.find_one('Version',
                                     [['id', 'is', versionInPlaylist['id']]],
                                     retFields))
            #for items in data:
            #   versionData.append({'name':items['code'],'desc':items['description'],'first_frame':items['self.sg_first_frame})
            return data

        def getTimeShot(self, shot):
            '''Given shot (as dict) return total time on shot as [0] and other times for each task on shot
            '''
            outputData = []
            retFields = ['content', 'time_logs_sum']
            totalTime = 0
            for curTask in shot['tasks']:
                taskData = self.sg.find_one('Task',
                                            [['id', 'is', curTask['id']]],
                                            fields=retFields)
                totalTime += taskData['time_logs_sum']
                outputData.append({
                    'name': taskData['content'],
                    'time': taskData['time_logs_sum']
                })
            outputData.insert(0, {'name': shot['code'], 'time': totalTime})
            return outputData
Пример #13
0
from tests import connect

from shotgun_api3 import Shotgun

if True:
    sg = connect()
else:
    sg = Shotgun('http://127.0.0.1:8020', 'name', 'key')

print sg.server_info


proj =  sg.create('Project', {'name': 'Mock Project Test'})
seq = sg.create('Sequence', {'code': 'AA', 'project': proj})
shot = sg.create('Shot', {'code': 'AA_001', 'sg_sequence': seq})

print proj
print seq
print shot
#
# print sg.find('Project', [('id', 'is_not', 0)], ['name'], order=[
#     {'field_name': 'id', 'direction': 'asc'},
# ])

print sg._call_rpc('count', None)
exit()

print sg.create('Project', {'name': 'Test Project'})
print sg.count()
print sg.find_one('Project', [], order=[
    {'field_name': 'id', 'direction': 'asc'},
from shotgun_api3 import Shotgun
import datetime
import os
import sys

# From env. variables
SERVER_PATH = os.environ.get("BASE_URL", "")
LOGIN = os.environ.get("USERNAME", "")
PASSWORD = os.environ.get("PASSWORD", "")
#
# Instantiate a connection object with Shotgun Server
sg = Shotgun(SERVER_PATH, login=LOGIN, password=PASSWORD)

if __name__ == "__main__":
    # Create a unique project name
    proj_name = datetime.datetime.now().strftime('%m-%d-%Y %H:%M:%S %f')
    proj_name = "Robot Project %s" % proj_name

    # Try to create a test project
    try:
        p = sg.create("Project", {"name": proj_name}, return_fields=["id"])
        id = p["id"]
        print id

    except Exception as E:
        print os.environ.get("TEST_PROJECT_ID")
Пример #15
0
class genericUtils:
    def __init__(self):
        self.sg = Shotgun('https://' + URL,name,API)

    def getFields (self, entity):
        '''get the fields for a type/entity as a list so we can pass it as an arg easily
        this is used all the time to make sure we get all the fields that we may ever need for a type/entity
        '''
        allFields = []
        fields = self.sg.schema_field_read(entity)
        for field in fields:
            allFields.append(field)
        return allFields  
    
    def project (self, project):
        '''Gets the Shotgun project name and ID
        '''
        retFields = self.getFields('Project')
        project = project.replace('_', ' ')
        return self.sg.find_one("Project", [["name", "is", project]], retFields )   

    def sequence (self, project, sequence):
        '''Returns the shotgun sequence name and ID 
        Parameters : (project, sequence)
        '''
        retFields = self.getFields('Sequence')
        return self.sg.find_one("Sequence", [["code", "is", sequence],['project','is',project]], retFields)
    
    def shot (self, project, shot):
        '''Returns the shotgun shot name and ID 
        Parameters : (project, shot)
        '''        
        retFields = self.getFields('Shot')
        return self.sg.find_one('Shot',[['code','is',shot],['project','is',project]],retFields)
    
    def createProject (self, project):
        '''Creates a project in Shotgun given a project name
        Parameters : (project)
        '''        
        filters = [['code','is','a']]
        template = self.sg.find_one('Project',[['name','is','a']],['layout_project','id'])
        data = {'name':project,
                'layout_project': template
                }
        return self.sg.create('Project',data)
    
    def createSequence (self, project, sequence):
        '''Creates a sequence in shotgun given 
        Parameters : (project, sequence)
        '''        
        data = {'project': {"type":"Project","id": project['id']},
                 'code': sequence}
        return self.sg.create('Sequence', data)
    
    def createShot (self, project, shot, seq='', taskTemplateName=''):
        '''Creates a sequence in shotgun given 
        Parameters : (project, shot, seq='', taskTemplateName='Basic shot template'
        '''          
        filters = [['code','is',taskTemplateName ]]
        template = self.sg.find_one('TaskTemplate',filters)
    
        data = { 'project': {"type":"Project","id": project['id']},
                 'code': shot,
                 'task_template' : template,
                 'description': '',
                 'self.sg_sequence': seq,
                 'self.sg_status_list': 'wtg' }
        result = self.sg.create('Shot', data)
        return result
    
    def notesFind (self, shotID):
        '''Find all notes on a shot 
        Parameters : (shotID)
        Output : Note data :
        ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
        addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
        'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
        'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
        '''
        note = self.sg.find('Note',[['note_links','is', shotID]],['subject','content', 'created_at'],[{'field_name':'created_at','direction':'desc'}])
        return note
    
    def notesFindLatest (self, shotID):
        '''Find the latest note on a shot
        Parameters : (shotID)
        Call with notesFindLatest(shot)['content'] for the note content only
        Output : Note data:
        ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
        addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
        'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
        'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
        '''
        note = self.notesFind(shotID)[0]
        return note
    
    
    def notesCreate(self, project, shotID, subject, content):
        '''Create a note for a shot given
        Parameters : (project, shotID, subject, content)
        Output : noteID
        '''
        # enter data here for a note to create
        data = {'subject':subject,'content':content,'note_links':[shotID],'project':project}
        # create the note
        noteID = self.sg.create('Note',data)
        return noteID
    
    def versionCreate(self, project, shot, verName, description, framePath, firstFrame, lastFrame, clientName=None, sourceFile=None, task=None, user=None, final=False, makeThumb=False, makeThumbShot=False):
        '''Create a version
        Parameters : (project, shotID, verName, description, framePath, firstFrame, lastFrame, clientName=None, sourceFile=None, task=None)
        Output : versionID
        '''
          
        data = {'project': project,
                'code': verName,
                'description': description,
                'sg_path_to_frames': framePath,
                #'sg_frame_range': str(firstFrame) + '-' + str(lastFrame),
                'sg_first_frame' : int(firstFrame),
                'sg_last_frame' : int(lastFrame),
                'sg_status_list': 'rev',
                'entity': shot}
        #if user != None:
            #data['user']
        if task != None:
            filters = [['content','is',task],['entity','is',shot]]
            taskID = self.sg.find_one('Task',filters)  
            data['sg_task']=taskID
        #if final == True and 'send
        # in case we're putting a client version in here we need this code.
        # we are expecting a field called self.sg_client_name in the version table.
        # please make sure you create this in the shotgun setup
        # read the schema and if the client_name is not found, create it.
        '''
        versionFields = self.sg.schema_field_read('Version')
        if 'sg_client_name' not in versionFields and clientName != None:
            newField = self.sg.schema_field_create('Version','text','Client Name')
        if clientName != None :
            data['sg_client_name'] =  clientName
    
        #'user': {'type':'HumanUser', 'id':165} }
        # here we need to create a field for storing the source file that created this version.
        # if it's not there, create the field, and if it's there just update it.
        
        if 'sg_source_file' not in versionFields and sourceFile != None:
            newField = self.sg.schema_field_create('Version','text','Source File')
        if sourceFile != None:
            data['sg_source_file'] = sourceFile
        '''
        
        versionData = self.sg.create('Version',data)
        # handle the thumbnail grabbing here
        middleFrame = (int(firstFrame) + int(lastFrame)) / 2
        padding, padString = fxpipe.framePad(framePath)
        paddedFrame = padString % (middleFrame)
        if makeThumb == True:
            thumbData = self.sg.upload_thumbnail('Version', versionData['id'], framePath.replace(padding,paddedFrame))
        if makeThumbShot == True:
            thumbData = self.sg.upload_thumbnail('Shot', shot['id'], framePath.replace(padding,paddedFrame))   
        return versionData      

   
    #add a task version to the system
    def versionCreateTask(self, project, shot, verName, description, framePath, firstFrame, lastFrame, task, sourceFile = ''):
        '''
        DEPRECATED : USE versionCreate instead with the task='TASKNAME'
        Parameters : (project, shot, verName, description, framePath, firstFrame, lastFrame, task, sourceFile = '')
        Output : Version ID
        '''
        filters = [['content','is',task],['entity','is',shot]]
        taskID = self.sg.find_one('Task',filters)
        data = {'project': project,
                'code': verName,
                'description': description,
                'self.sg_path_to_frames': framePath,
                'frame_range': str(firstFrame) + '-' + str(lastFrame),
                'self.sg_first_frame' : firstFrame,
                'self.sg_last_frame' : lastFrame,
                #'self.sg_uploaded_movie': '/Users/throb/Downloads/test.m4v',
                #'self.sg_first_frame': 1,
                #'self.sg_last_frame': 100,
                'self.sg_status_list': 'rev',
                'self.sg_task': taskID,
    
                'entity': shot}
        # here we need to create a field for storing the source file that created this version.
        # if it's not there, create the field, and if it's there just update it.
        try:
            tmp2 = {}
            tmp2 = tmp['self.sg_source_file']
        except:
            newField = self.sg.schema_field_create('Version','text','Source File')
        if sourceFile != '':
            data['self.sg_source_file'] = sourceFile
    
        return self.sg.create('Version',data)
    # look for specific version
    def versionFind(self, versionID):
        '''Find all versions in a shot with most recent first
        Parameters : (shotID)
        Output : Version data:
        ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
        'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
        'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
        'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
        'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
        'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
        'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
        'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
        '''        
        retFields = self.getFields('Version')
        return self.sg.find('Version',[['id','is',versionID]],retFields,[{'field_name':'created_at','direction':'desc'}])[0]
    
    # look for versions in a shot:
    def versionFindShot(self, shotID):
        '''Find all versions in a shot with most recent first
        Parameters : (shotID)
        Output : Version data:
        ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
        'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
        'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
        'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
        'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
        'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
        'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
        'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
        '''        
        retFields = self.getFields('Version')
        return self.sg.find('Version',[['entity','is',shotID]],retFields,[{'field_name':'created_at','direction':'desc'}])
    
    def versionFindLatest(self, shotID):
        '''Find only the most recent version
        Parameters : (shotID)
        Output : Version data:
        ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
        'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
        'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
        'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
        'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
        'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
        'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
        'filmstrip_image', 'tag_list', 'frame_count', 'flagged']         
        '''
        retFields = self.getFields('Version')
        return self.sg.find_one('Version',[['entity','is',shotID]],retFields,[{'field_name':'created_at','direction':'desc'}])
    
    # search for the latest task given shotID and task info
    def versionFindLatestTask(self, shotID, task):
        retFields = self.getFields('Version')
        # first look for the task and get the ID
        filters = [['content','is',task],['entity','is',shotID]]
        taskID = self.sg.find_one('Task',filters)
        # then look for the latest
        #version using the task ID.  note that we need to use the [0] or else we're sending the array versus the hash
        versionLatest = self.sg.find_one('Version',[['entity','is',shotID],['self.sg_task','is',taskID]],retFields,[{'field_name':'created_at','direction':'desc'}])
        return versionLatest
    
    ## The following requires a field called "client_version" be added to shotgun
    def versionClientUpdate (self, shotID, version, clientVersionName ='Client Version'):
        '''This takes the shotID and version (int) and updates the shot with this client version number
        Sometimes the client wants to see different version numbers versus the internal ones.  This option allows for it.
        You will need to create a field.  Client Version is what I have used but you can specify what you want here.
        Parameters: (shotID, version, clientVersionName ='Client Version')
        Output : Version data
        '''
        sgFieldName = 'sg_' + clientVersionName.lower().replace(' ','_')
        data = { sgFieldName: version}
        try:
            result = self.sg.update('Shot', shotID['id'], data)
        except:
            newField = self.sg.schema_field_create('Shot', 'number', clientVersionName)
            result = self.sg.update('Shot', shotID['id'], data)
        return result
    

    def uploadQT (self, entityType, item, path):
        '''Upload a file to shotgun in the 'self.sg_qt' field.
        If you do this for a shot, you will need to add this to a field
        the field should be called 'qt' as shotgun will add the self.sg_ to it
        Shotgun provides the self.sg_qt for versions automatically
        Parameters: (entity,item,path)
        uploadQT ('Version',versionData, '/my/file.mov')
        '''
        # Make sure first letter is capitalized
        entity = entityType.capitalize()

        # upload that mother
        if entity.lower() == 'shot':
            try:
                result = self.sg.upload (entity, item['id'], path,'sg_qt')
            except:
                newField = self.sg.schema_field_create('Shot', 'url', 'QT')
                result = self.sg.upload (entity, item['id'], path,'sg_qt')
    
        elif entity.lower() == 'version':
            result = self.sg.upload (entity, item['id'], path,'sg_uploaded_movie')
        return result
    
 
    def versionClientGet (self, shotID, clientVersion='Client Version'):
        '''Get latest client version number
        Parameters : (hotID, clientVersion='Client Version')
        Output : Version data
        '''        
        sgFieldName = 'sg_' + clientVersionName.lower().replace(' ','_')
        try :
            currentVersion = shotID[sgFieldName]
        except :
            currentVersion = 0
        if currentVersion == None:
            return 0
        return currentVersion
    
    def playlistFind (self, project, playlistName):
        '''Search for a playlist given a project and name
        Parameters : (project, playlistName)
        Output : playlist data:
        ['code', 'description', 'versions', 'created_at', 'sg_cinesync_session_url', 
        'updated_at', 'created_by', 'project', 'filmstrip_image', 'notes', 'image', 
        'updated_by', 'sg_cinesync_session_key', 'sg_status', 'tag_list', 'id', 
        'sg_date_and_time']        
        '''        
        retFields = self.getFields('Playlist')
        return self.sg.find_one('Playlist',[['code','is',playlistName],['project','is',project]],retFields)
    
    def playlistCreate (self, project, playlistName, playlistDescription=''):
        '''Create a playlist given a playlist name
        Parameters : (project, playlistName, playlistDescription='')
        Output : playlist data
        '''        
        data = {'project':project,'code':playlistName, 'description':playlistDescription}
        return self.sg.create('Playlist',data)
    
    # Add a version to a playlist
    def playlistAddVersion (self, project, playlistName, version):
        '''
        Description :\n
        This adds a version (existing version in the system) to a playlist.\n
        You need to give it: (in order)\r
        shotgun connection class\r
        project (dict of the project info including name and id)\r
        playlist name (string of the name of the playlist)\r
        version (dict of the version you wish to add\n
        It will return with a dict of the playlist
        '''
    
        my_playlist_list = self.sg.find_one('Playlist',[['code','is',playlistName],['project','is',project]],['versions']);
        if len(my_playlist_list):
            ver_list = my_playlist_list['versions'];
            ver_list.append({'type':'Version','name':version['code'],'id':version['id']})
            result = self.sg.update('Playlist', my_playlist_list['id'], {'versions' : ver_list})
            return result
    
    def playlistInfo (self, project, playlistName):
        '''Get playlist info (eg version name and description)
        Parameters : (project, playlistName)
        Output : version data
        '''        
        data = []
        versionData = []
        retFields = self.getFields('Version')
        for versionInPlaylist in self.sg.find_one('Playlist',[['code','is',playlistName],['project','is',project]],['versions'])['versions']:
            data.append (self.sg.find_one('Version',[['id','is',versionInPlaylist['id']]],retFields))
        #for items in data:
         #   versionData.append({'name':items['code'],'desc':items['description'],'first_frame':items['self.sg_first_frame})
        return data        
    
    def getTimeShot(self, shot):
        '''Given shot (as dict) return total time on shot as [0] and other times for each task on shot
        '''
        outputData = []
        retFields = ['content','time_logs_sum']
        totalTime = 0
        for curTask in shot['tasks']:
            taskData = self.sg.find_one('Task',[['id','is',curTask['id']]],fields=retFields)
            totalTime += taskData['time_logs_sum']
            outputData.append({'name':taskData['content'],'time':taskData['time_logs_sum']})
        outputData.insert(0,{'name':shot['code'],'time':totalTime})
        return outputData
Пример #16
0
from shotgun_api3 import Shotgun

blob = yaml.load(sys.stdin)
method = sys.argv[1]

config = blob['config']
payload = blob['data']

sg = Shotgun(config['shotgun_url'], config['script_name'], config['script_api_key'], 'api3_preview')

if method == 'find':
  result = sg.find(payload['entity'], payload['filters'], payload['fields'], payload['order'], payload['filter_operator'], payload['limit'], payload['retired_only'])
elif method == 'find_one':
  result = sg.find_one(payload['entity'], payload['filters'], payload['fields'], payload['order'], payload['filter_operator'])
elif method == 'create':
  result = sg.create(payload['entity'], payload['data'])
elif method == 'update':
  result = sg.update(payload['entity'], payload['id'], payload['data'])
elif method == 'delete':
  result = sg.delete(payload['entity'], payload['id'])
elif method == 'upload':
  result = sg.upload(payload['entity'], payload['id'], payload['path'], payload['field_name'], payload['display_name'])
elif method == 'upload_thumbnail':
  result = sg.upload_thumbnail(payload['entity'], payload['id'], payload['path'])
elif method == 'schema_field_read':
  result = sg.schema_field_read(payload['entity'])
elif method == 'schema_field_create':
  result = sg.schema_field_create(payload['entity'], payload['type'], payload['name'], payload['attrs'])
elif method == '_url_for_attachment_id':
  entity_id = payload['id']
Пример #17
0
        data = {'firstname': firstName, 'lastname': lastName, 'email': userMail,
                'sg_status_list': 'dis', 'login': '******'.format(firstName,lastName)}
        fields = ['id']
        user = self.sg.create('HumanUser', data, fields)
        print user
        return user


    def createTask(self, projectID, entityType, entityID, taskName):
        data = {'project': {'type': 'Project', 'id': projectID},
                'task_assignees': [{'type': 'HumanUser', 'id': 86, 'name': 'Huevo Cartoon'}],
                'content': taskName, 'entity': {'type': entityType, 'id': entityID}
                }

        fields = ['id']
        task = self.sg.create('Task', data, fields)
        print task
        return task


SERVER_PATH = "https://hcpstudio.shotgunstudio.com"
SCRIPT_NAME = 'sgApi'
SCRIPT_KEY = '3899a8466f2cea694c2ba5341d871da845509d18d96a4feb7fb8d147de0fa819'
sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
data = {'name': 'Test0001', 'sg_status': 'Active', 'sg_type': 'Feature'}
fields = ['id']
project = sg.create('Project', data, fields)
print project

Пример #18
0
class ShotgunUtils():
    '''
    this module is a collection of functions to conect the Asset manager to shogun studio website, to update, create
    and manages all attributes and parameters from the different entities.
    '''

    def __init__(self):
        '''
        creates the connection to the server and connects to database.
        creates list of Ids form the  database collections that needs to convert to shotgun collections

        '''

        SERVER_PATH = "https://hcpstudio.shotgunstudio.com"
        SCRIPT_NAME = 'sgApi'
        SCRIPT_KEY = '3899a8466f2cea694c2ba5341d871da845509d18d96a4feb7fb8d147de0fa819'

        self.sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)

        self.dbObjectID = ObjectId()

        master = DaoMaster()
        session = DaoMaster.getSession()

        self.itemInstance = session.getItemsDao()

        self.ItemStatusList = ['rdy', 'ip', 'app', 'crnt', 'outd','dep', 'vari', 'rej']

        self.ItemType = ['Source', 'Prop', 'Environment', 'Character', 'Rig', 'Fx', 'Template', 'Geometry', 'Art',
                         'Shader', 'Texture', 'Cache', 'ImageSequence', 'DCC', 'None']

        self.ItemClass = ['Item', 'Asset', 'superAsset']

    def getParameterSchema(self, fieldType, fieldName = None):
        '''
         utility function to search fields in a given entity.
        :param fieldType: entity to search parameters 'Project', 'Sequence', 'Shot', 'Asset', 'Version', etc.
        :param fieldName: name of the field to search 'id', 'name', 'coce', etc.
        :return: retruns a dictionary with the properties of given parameter
        '''

        squemaDic = self.sg.schema_field_read(fieldType, fieldName)
        print squemaDic
        for field in squemaDic:
            print field
        return squemaDic

    def getEntities(self):
        '''
        utility function to find all the Entities in shotgun for developing
        :return: renturn a list of all entities
        '''
        squemaDic = self.sg.schema_entity_read()
        for entity in squemaDic:
            print entity
        return squemaDic


    def createProject(self, sgName, sgStatus, sgType):
        ''' creates a Project using the given name, status, type,start date, end date.
            the status parameter is a list::
                Bidding
                Active
                Lost
                Hold

            the type parameter is a list:
                Feature
                Episodic
                Commercial
                Game Cinematic
                AAA Game
                Mobile Game
                Audio
                Mocap
                Misc
        '''
        data = {'name': sgName, 'sg_status': 'Active', 'sg_type': 'Feature'}
        fields = ['id']
        project = self.sg.create('Project', data, fields)
        return project

    def createSequence(self, projectID, sqName):
        '''
        creates a Sequence for the project set by the Id,
        :return: a dictionary containing the basic info of the sequence
        '''

        data = {'project': {'type': 'Project', 'id': projectID},
            'code': sqName}
        fields = ['id']
        sequence = self.sg.create('Sequence', data, fields)
        print sequence
        return sequence

    def createShot(self, projectID, shotName, sqID):

        data = {'project': {'type': 'Project', 'id': projectID},
            'code': shotName, 'sg_sequence': {'type': 'Sequence', 'id': sqID}}

        fields = ['id']
        shot = self.sg.create('Shot', data, fields)
        print shot
        return shot

    def createItem(self, projectID, itemName, itemType):
        '''
        creates an Item from an existing one inside the assetManager, use the parameters of given mongo objcet
        and updates the id of the mongo object with the shotgunId attribute of the mongo object.
        :return: a dictionary with the parameters defined in shotgun
        '''

        data = {'project': {'type': 'Project', 'id': projectID},
            'code': itemName, 'sg_asset_type': itemType}

        fields = ['id']
        item = self.sg.create('Asset', data, fields)
        print item
        return item

    def createDigitalMedia(self, projectID, dmName, dmType, taskID, entityType, entityID):

        data = {'project': {'type': 'Project', 'id': projectID},
            'code': dmName, 'sg_version_type': dmType, 'sg_task': {'type': 'Task', 'id': taskID},
            'entity': {'type': entityType, 'id': entityID}
                }

        fields = ['id']
        dm = self.sg.create('Version', data, fields)
        print dm
        return dm

    def createUser(self, firstName, lastName, userMail):

        data = {'firstname': firstName, 'lastname': lastName, 'email': userMail,
                'sg_status_list': 'dis', 'login': '******'.format(firstName,lastName)}
        fields = ['id']
        user = self.sg.create('HumanUser', data, fields)
        print user
        return user


    def createTask(self, projectID, entityType, entityID, taskName):
        data = {'project': {'type': 'Project', 'id': projectID},
                'task_assignees': [{'type': 'HumanUser', 'id': 86, 'name': 'Huevo Cartoon'}],
                'content': taskName, 'entity': {'type': entityType, 'id': entityID}
                }

        fields = ['id']
        task = self.sg.create('Task', data, fields)
        print task
        return task
Пример #19
0
     'sg_path_to_frames': os.path.dirname(r),
     'sg_status_list': 'rev',
     'entity': {
         'type': 'Shot',
         'id': sid
     },
     'sg_task': {
         'type': 'Task',
         'id': tid
     },
     'user': {
         'type': 'HumanUser',
         'id': uid
     }
 }
 v = sg.create('Version', data)
 if v != None:
     vid = v['id']
     rps = r.split('/')
     # ---------- drive -------- shotgun ------ project ------ scene -------- shot --------- task --------- review
     reviewpath = rps[0] + '/' + rps[
         1] + '/' + rps[2] + '/' + rps[
             3] + '/' + rps[4] + '/' + rps[
                 5] + '/' + "review" + '/'
     if not os.path.exists(reviewpath):
         os.mkdir(reviewpath)
     reviewvid = reviewpath + os.path.basename(
         rvid)
     shutil.copy2(rvid, reviewvid)
     sg.upload_thumbnail("Version", vid, r)
     sg.upload("Version", vid, reviewvid,
Пример #20
0
class DBase(object):
    """Wrapper for database, currently it's Shotgun"""



    def __init__(self):

        sgSite = 'https://chimneypot.shotgunstudio.com'
        scriptName = 'dBase'
        scriptKey = '729a76955455909c79f6d90262bb9fbe9186b92b'

        self.db = Shotgun(sgSite, scriptName, scriptKey)
        
        
    def getProjectsDict(self, status='Active', owner='kiev'):
        
        filters = [ ['sg_status', 'is', status],
                ['sg_project_owner', 'is', owner]
                ]
        fields = ['name', 'id']
        projectsListRaw = self.db.find("Project", filters, fields)
        projectDict = {x['name']:x['id'] for x in projectsListRaw}

        return projectDict

    def getSequencesDict(self, projId):

        filters = [['project','is',{'type':'Project','id':projId}]]
        fields = ['code', 'id']
        sequencesListRaw = self.db.find("Sequence", filters, fields)
        sequencesDict = {x['code']:x['id'] for x in sequencesListRaw}

        return sequencesDict
    
    def getShots(self, seqId):

        filters = [['sg_sequence','is',{'type':'Sequence','id':seqId}]]
        fields = ['code', 'id']
        sequencesListRaw = self.db.find("Shot", filters, fields)
        sequencesDict = {x['code']:x['id'] for x in sequencesListRaw}

        return sequencesDict    

    def addProject(self, projName, status='Active', owner='kiev'):

        data = {
            'name': projName,
            'sg_status': status,
            'sg_project_owner': owner
            }

        newProj = self.db.create('Project', data)

        return newProj

    def addSequence(self, seqName, projId):

        data = {
            'project': {'type': 'Project', 'id': projId},
            'code': seqName
            }

        newSeq = self.db.create('Sequence', data)

        return newSeq

    def addShot(self, shName, seqId, projId):

        data = {
            'project': {'type': 'Project', 'id': projId},
            'sg_sequence': {'type': 'Sequence', 'id': seqId},
            'code': shName
            }

        newSh = self.db.create('Shot', data)

        return newSh       



    def getProject(self, projId):
        
        filters = [['id', 'is', projId]]
        fields = ['name']
        proj = self.db.find_one("Project", filters, fields)

        return proj

    def getSequence(self, seqId):
        
        filters = [['id', 'is', seqId]]
        fields = ['code', 'project', 'shots']
        seq = self.db.find_one("Sequence", filters, fields)

        return seq

    def getShot(self, shId):

        filters = [['id', 'is', shId]]
        fields = ['code', 'project', 'sg_sequence', 'tasks']
        sh = self.db.find_one("Shot", filters, fields)

        return sh
class PublishMayaAudio(QWidget):
    def __init__(self, defaultSource = 'I:/lsapipeline/audios/', parent = None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Audio Publishing Tool')
        self.parent = parent
        ## Connect to shotgun
    
        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun. 
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key     = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'
        
        self.sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        
        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = {}
        
        ## Build the UI
        self.mainLayout = QVBoxLayout(self)
        
        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.epNumber.textChanged.connect(self.epTextChange)   
        self.epNumber.setText('ep')
        
        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button        
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        if self.sourceFolder:
            self.sourceInput.setText(self.sourceFolder)
        self.sourceInput.textChanged.connect(partial(self.doFileCheckboxes))
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(partial(self._browseDialog, dest = False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)       
        self.pathLayout.addWidget(self.browseButton)        
        
        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')
        
        self.goButton = QPushButton('Publish Audio Files')
        self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
        self.goButton.clicked.connect(self._doit)
        
        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)
        
        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)
        
        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)
        
        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)
        
        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)
        
        self.fileLayout = QGridLayout(self.filesGroupBox)
        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('Publish Audio Files')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)
                
    def doFileCheckboxes(self, myPath = ''):
        """
        Process all the folders/files found into check boxes for processing
        """ 
        ## try to get the epNumber from a file
        epNum = os.listdir(self.sourceInput.text())[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)
            
        if self.fileBoxes != {}:
            for key, var in self.fileBoxes.items():
                key.setParent(None)
                sip.delete(key)
                key = None
        
        self.repaint()
        self.files      = []
        self.fileBoxes  = {}
       
        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL') 
        self.ALL.toggled.connect(self._toggleAll)
        
        self.fileBoxes[self.ALL] =  None
        self.fileLayout.addWidget(self.ALL, 0, 0)
        
        self.colCount = 10
        r = 1
        c = 1
        
        ## Now process the folder and add the folders found as check boxes.
        try:
            ## Scan the entire folder structure for audio files to publish
            if self.isRootFolderThere(rootFolder = self.sourceFolder):
                print '%s found processing now...' % self.sourceFolder
                for dirname, dirnames, filenames in os.walk(self.sourceFolder):
                    if dirname.endswith('\\wav'):
                        print  'Scanning %s now..' % dirname
                        print 'Files: %s' % os.listdir(dirname)
                        getMaxFile = max(os.listdir(dirname))
                        if getMaxFile: ## we have a folder with files in it...
                            if getMaxFile.endswith(".wav"):
                                pathToWav = os.path.join(dirname, getMaxFile)
                                self.fileCheckBox = QCheckBox(self)
                                self.fileCheckBox.setChecked(False)
                                self.fileCheckBox.setText(getMaxFile)
                                self.fileBoxes[self.fileCheckBox] = pathToWav.replace('\\', '/')
                                 
                                if c == self.colCount:
                                    r = r + 1
                                    c = 1
                                self.fileLayout.addWidget(self.fileCheckBox, r, c)
                                c = c + 1
                                print 'Adding %s to layout now..' % pathToWav
                        else:
                            print '%s is emtpy...' % dirname
            else:
                self.files =  ['No root folder found...']
        except:
            self.files =  ['No wav files found...']

    def _browseDialog(self, dest = False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """

        if sys.platform == 'win32':
            print 'OPENING WIN BROWSE DIALOG NOW...'
            myPath = QFileDialog(self, 'rootDir', self.sourceFolder).getExistingDirectory().replace('\\', '/')
        else:
            print 'OPENING %s BROWSE DIALOG NOW...' % sys.platform
            myPath = QFileDialog(self, 'rootDir', self.sourceFolder).getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]
        
        if epNum:
            self.epNumber.setText(epNum)
        
        self.sourceFolder = str(myPath)

        os.system('echo epNum: %s' % self.epNumber)
        os.system('echo sourceFolder: %s' % self.sourceFolder)
        os.system('echo final myPath: %s' % myPath)
        self.sourceInput.setText(myPath)
        
        #self.doFileCheckboxes(myPath)
        
            
                 
    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.wav')[0]) + 1 
    
    def _writeMaFile(self, fileName, pathToWav, wavName, publishPath):
        ## Check the folder exists, if not make one now.
        if not os.path.isdir(os.path.dirname(self.publishPath)):
            os.makedirs(os.path.dirname(self.publishPath))
        
        self.header = [
        r'//Maya ASCII 2013ff10 scene',
        r'//Name: %s' % fileName,
        r'//Last modified: Tue, Jun 17, 2014 10:41:32 AM',
        r'//Codeset: 1252',
        r'requires maya "2013ff10";',
        r'requires "Mayatomr" "2013.0 - 3.10.1.11 ";',
        r'currentUnit -l centimeter -a degree -t film;',
        r'fileInfo "application" "maya";',
        r'fileInfo "product" "Maya 2013";',
        r'fileInfo "version" "2013 x64";',
        r'fileInfo "cutIdentifier" "201301140020-856945";',
        r'fileInfo "osv" "Microsoft Windows 7 Ultimate Edition, 64-bit Windows 7 Service Pack 1 (Build 7601)\n";',
        ]
        
        self.audioNode = [
                        '\n%s' % r'createNode audio -n "%s";' % wavName.replace('.', '_'),
                            '\t%s' % r'setAttr ".ef" 1000;',
                            '\t%s' % r'setAttr ".se" 1000;',
                            '\t%s' % r'setAttr ".f" -type "string" "%s";' % pathToWav,
                          ]
        
        self.footer = [
                       '\n%s' % r'// End of %s.ma' % fileName]
        
        ## Now write the ma file
        ## Fail if the version already exists
        pathToTextFile = publishPath
        if not os.path.isfile(pathToTextFile):
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)
            
            outfile.close()
        else:
            ## Remove it because we are republishing the same version again.
            os.remove(pathToTextFile)
            ## Note we can just delete this file already and move on if needed.
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)
            
            outfile.close()
    
    def _createPublish(self, publishPath, fileName, pathToWav, wavName, version_number, localPath, localPathMac, wavSGName, ctx):
        self.pathToWav      = pathToWav
        self.publishPath    = publishPath
        self.localPath      = localPath
        self.localPathMac   = localPathMac
        self.fileName       = fileName
        self.wavName        = wavName
        self.wavSGName      = wavSGName
        self.version_number = version_number


        data = {
                "code"          : self.wavSGName,
                "description"   : None,
                "name"          : self.wavSGName,
                "project"       : ctx.project,
                "entity"        : {'id': self.exists['id'], 'name': self.wavSGName, 'type': 'CustomEntity03'},
                "version_number": self.version_number,
                'path_cache'    : self.publishPath.replace('/', '\\'),
                'published_file_type' : {'type' : 'PublishedFileType', 'id': 1},
                'updated_by'    : {
                               'type' : 'HumanUser', 'id' : 53
                               },
                'path'         : {
                              'content_type': None,
                              'link_type': 'local',
                              'url': 'file:///%s' % self.publishPath.replace('/', '\\'),
                              "local_path": self.publishPath.replace('/', '\\'),
                              'local_path_linux': '',
                              'local_path_mac': '%s' % self.localPathMac,
                              'local_path_windows': '%s' % self.publishPath.replace('/', '\\'),
                              'local_storage': {'id': 1, 'name': 'primary', 'type': 'LocalStorage'},
                              'name': self.fileName,
                                }
                }
        
        self.sgsrv.create('PublishedFile', data)
        print 'Publish file created for %s' % self.wavSGName
    
    def _publishAudio(self):
        """
        Function to add the publish a maya audio file both making a maya file with an audio node and publishing this to shotgun as a version
        """
        for key, var in self.fileBoxes.items():
            if var:
                if key.isChecked():
                    ## Work out what we need for the creation of the ma file 
                    ## and the publish for shotgun
                    self.pathToWav      = var
                    if sys.platform == 'win32':
                        self.publishPath = var.replace('/publish/wav', '/publish/maya').replace('.wav', '.ma').replace('/', '\\')
                    self.localPath      = self.publishPath.split('I:')[-1]
                    self.localPathMac   = self.publishPath.replace('I:', '/_projects')
                    self.fileName       = str(key.text()).replace('.wav', '.ma')
                    self.wavName        = str(key.text())
                    self.wavSGName      = str(key.text().replace('_AUD', '').split('.')[0])
                    self.version_number = int(str(key.text()).split('.')[-2].split('v')[-1])
                    
                    ## Now register the publish with Shotgun
                    ## First find the audio on shotgun for processing. 
                    self.exists         =  self.sgsrv.find_one('CustomEntity03',  filters = [["code", "is", self.wavSGName]], fields=['code', 'tasks', 'id'])

                    if not self.exists:
                        print '%s has no shotgun entry! You should make sure this has been processed correctly before proceeding!!' % self.wavName

                    else:
                        ## now publish
                        tk = sgtk.sgtk_from_path("I:/lsapipeline/")
                        ctx = tk.context_from_path(self.publishPath)
                        
                        ## For existing check
                        ## CHECK FOR EXISTING PUBLISH WITH THE SAME VERSION NUMBER!!!!
                        findExisting = self.sgsrv.find_one('PublishedFile', filters = [["code", "is", self.wavSGName]], fields=['code', 'id', 'version_number', 'created_at', 'entity'])
                        if findExisting:
                            if findExisting['version_number'] == self.version_number:
                                print 'A PUBLISHED FILE FOR THIS VERSION ALREADY EXISTS SKIPPING! VERSION UP OR DELETE EXISTING SHOTGUN PUBLISH ENTRIES IF YOU NEED TO YOU SHOULDNT BUT YOU MIGHT!'
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName, self.pathToWav, self.wavName, self.publishPath)
                            else:## This is a new version number
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName, self.pathToWav, self.wavName, self.publishPath)
                                self._createPublish(publishPath = self.publishPath, fileName = self.fileName, pathToWav = self.pathToWav, wavName = self.wavName, version_number = self.version_number,
                                               localPath = self.localPath, localPathMac = self.localPathMac, wavSGName = self.wavSGName, ctx = ctx)
                        else:## nothing already exists so build a fresh publish
                            ## WRITE THE MA
                            ## Now write the ma file we are going to publish with the audio node created.
                            ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                            self._writeMaFile(self.fileName, self.pathToWav, self.wavName, self.publishPath)
                            self._createPublish(publishPath = self.publishPath, fileName = self.fileName, pathToWav = self.pathToWav, wavName = self.wavName, version_number = self.version_number,
                                           localPath = self.localPath, localPathMac = self.localPathMac, wavSGName = self.wavSGName, ctx = ctx)
                        
        print 'Complete'
        self.goButton.setText('COMPLETE.. click to run again')
        self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')
        self.repaint()
        
    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.repaint()
        return True
        
    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet('QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}')
                self.reply = QMessageBox.question(self, 'Nope!', "Nothing to transfer. Try selecting something and try again", QMessageBox.Ok)
            else:
                self._publishAudio()

    def isRootFolderThere(self, rootFolder):
        """
        Method used to check if root folder is valid or not
        """
        if not os.path.isdir(rootFolder):
            print 'No such root folder found.'
            return -1
        else:
            return 1
class StoryboardFileManagement(QWidget):
    def __init__(self, defaultSource = '', parent = None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('StoryBoard File Processing')
        self.parent = parent
        ## Connect to shotgun
    
        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun. 
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key     = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'
        
        print 'Connecting to shotgun....'
        self.sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        
        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = []
        
        ## Build the UI
        self.mainLayout = QVBoxLayout(self)
        
        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.epNumber.textChanged.connect(self.epTextChange)   
        self.epNumber.setText('ep')
        
        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button        
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        self.sourceInput.textChanged.connect(self.doFileCheckboxes)
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(partial(self._browseDialog, dest = False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)       
        self.pathLayout.addWidget(self.browseButton)        
        
        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')
        
        self.goButton = QPushButton('Transfer SBrd Files To Episode Version Folders')
        self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
        self.goButton.clicked.connect(self._doit)
        
        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)
        
        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)
        
        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)
        
        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)
        
        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)
        
        self.fileLayout = QGridLayout(self.filesGroupBox)
        
        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('Transfer SBrd Files To Episode Version Folders')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)
                
    def doFileCheckboxes(self, myPath = ''):
        """
        Process all the folders/files found into checkboxes for processing
        """ 
        ## try to get the epNumber from a file
        epNum = str(os.listdir(self.sourceInput.text())[0].split('_')[0])
        if epNum == '.DS' or epNum == '.DS_Store':
            getFiles = os.listdir(self.sourceInput.text())
            for each in getFiles:
                if ".mov" in each:
                    epNum = each.split('_')[0]
        #print 'I AM A BAD NAUGHTY VARIABLE!: %s' % epNum

        if epNum:
            self.epNumber.setText(epNum)
            
        if self.fileBoxes != []:
            for each in self.fileBoxes:
                each.setParent(None)
                sip.delete(each)
                each = None

        self.files = []
        self.fileBoxes = []
       
        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL') 
        self.ALL.toggled.connect(self._toggleAll)
        
        self.fileBoxes.append(self.ALL)
        self.fileLayout.addWidget(self.ALL, 0, 0)
        
        ## Now process the folder and add the folders found as checkboxes.
        try:
            if myPath:
                if sys.platform == 'win32':
                    self.sourceFolder = myPath.replace('/', '\\')
                else:
                    self.sourceFolder = myPath
            else:
                self.sourceFolder = str(self.sourceInput.text())

            for eachFile in os.listdir(self.sourceFolder):
                if eachFile.endswith('.mov'):
                    self.files.append(eachFile)
        except:
            self.files =  ['No mov files found...']

        self.colCount = 10
        r = 1
        c = 1
        for eachType in sorted(self.files):
            self.fileCheckBox = QCheckBox(self)
            self.fileCheckBox.setChecked(False)
            self.fileCheckBox.setText(eachType)
            self.fileBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.fileLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1

    def _browseDialog(self, dest = False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """
        try:
            if sys.platform == 'win32':
                myPath = QFileDialog(self, 'rootDir', 'O:/EPISODE DELIVERY').getExistingDirectory().replace('\\', '/')
            else:
                myPath = QFileDialog(self, 'rootDir', '/Volumes/LemonSky/OUT TO LEMONSKY/EPISODE DELIVERY').getExistingDirectory().replace('\\', '/')
        except :
            myPath = QFileDialog(self, 'rootDir', '').getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)
        self.sourceInput.setText(myPath)
        self.sourceFolder = str(myPath)
        self.doFileCheckboxes(myPath)
                 
    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.mov')[0]) + 1 
    
    def addStoryboardVersionToShotgun(self, path, epName, shotName, verNum, fullVersPublishName):
        """
        Function to add the audio asset to shotgun correctly for tasks etc and the pipeline to see it
        """
        #self.shotNum = each.text().split('.mov')[0]
        #self.addStoryboardVersionToShotgun(str(self.shotReviewDir), str(self.epName), self.shotNum, self.vNum, self.shotReviewFileName)
        ## Now start processing stuff..
        self.epName     = epName.lower()
        self.shotName   = shotName.lower()
        self.boardName  = fullVersPublishName.lower()
        self.taskName   = 'StoryBoard'
        self.sg_version = verNum
               
        self.pathToMovie = '%s%s' % (path, self.boardName)
        
        ## First find it the task exists
        self.getShotTasks =  self.sgsrv.find_one('Shot',  filters = [["code", "is", self.shotName]], fields=['id', 'tasks'])
        
        ## Now check and see if the task we need is there...
        self.tasks = []
        self.taskList = []
        if self.getShotTasks:
            for eachTaskDict in self.getShotTasks['tasks']:
                self.tasks.append(eachTaskDict['name'])
                self.taskList.append(eachTaskDict)

            if self.taskName not in self.tasks:
                ## Create new task for the shot
                self.myNewTask = self.sgsrv.create(
                                                   'Task', 
                                                   {
                                                    'project': 
                                                            {
                                                             'type': 'Project',
                                                             'id': 66
                                                             }, 
                                                    'step': {
                                                             'type': 'Step', 
                                                             'id': 72, 
                                                             'name': 'StoryBoard'
                                                            }, 
                                                    'content': 'StoryBoard',
                                                    'sg_status_list': 'apr',
                                                    'template_task': {
                                                                      'type': 'Task', 
                                                                      'id': 31333
                                                                      }
                                                    }
                                                   )
                self.taskId = int(self.myNewTask['id'])
                ## Returns {'project': {'type': 'Project', 'id': 66, 'name': 'bubblebathbay'}, 'step': {'type': 'Step', 'id': 72, 'name': 'StoryBoard'}, 'type': 'Task', 'id': 32335}
                 
                ## Add this dict to the list of dict for updating the shot task list with.
                self.taskList.append({'type': 'Task', 'id': self.myNewTask['id'], 'name': 'StoryBoard'})
    
                ## Now update the shots task list.
                self.sgsrv.update(
                                  'Shot', 
                                  self.getShotTasks['id'], 
                                  {
                                   'project': {
                                               'type':'Project',
                                               'id':66
                                               }, 
                                   'tasks': self.taskList
                                   }
                                  )
                print 'Successfully updated shot %s with task %s' % (self.shotName, self.taskId)
    
                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName, self.shotName)
                data = { 'project': {'type':'Project','id': 66},
                         'code': self.boardName,
                         'description': 'I am not a fluffy bunny!',
                         'sg_path_to_movie': self.pathToMovie,
                         'sg_status_list': 'rev',
                         'entity': {'type':'Shot', 'id':self.getShotTasks['id']},
                         'sg_task': {'type':'Task', 'id':self.taskId},
                         'sg_status_list': 'vwd',
                         'user': {'type':'HumanUser', 'id':53} }
                result = self.sgsrv.create('Version', data)
                
                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName, self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'], self.pathToMovie, "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)
            else:
                ## Get the story board task id
                for eachTask in self.taskList:
                    if eachTask['name'] == 'StoryBoard':
                        self.taskId = eachTask['id']
                
                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName, self.shotName)
                data = { 'project': {'type':'Project','id': 66},
                         'code': self.boardName,
                         'description': 'I am not a fluffy bunny!',
                         'sg_path_to_movie': self.pathToMovie,
                         'sg_status_list': 'rev',
                         'entity': {'type':'Shot', 'id':self.getShotTasks['id']},
                         'sg_task': {'type':'Task', 'id':self.taskId},
                         'sg_status_list': 'vwd',
                         'user': {'type':'HumanUser', 'id': 53} }
                result = self.sgsrv.create('Version', data)
                
                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName, self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'], self.pathToMovie, "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)

        else:
            print 'NO TASKS EXIST FOR %s skipping...' % self.shotName 
            self._turnOffCheckBox('%s.mov' % self.shotName)
        
    def _turnOffCheckBox(self, shotName):
        """
        Func for turning off the uploaded movies as we progress through them so if we error out we have 
        a way to see what has been processed already
        """
        for each in self.fileBoxes:
            if str(each.text()) == shotName:
                each.setChecked(False)
                self.repaint()    

    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.repaint()
        return True
        
    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet('QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}')
                self.reply = QMessageBox.question(self, 'Nope!', "Nothing to transfer. Try selecting something and try again", QMessageBox.Ok)
            else:
                self.processStoryBoardFolder()
    
    def processStoryBoardFolder(self):
        """
        Function to copy over all the audio files from a single output folder into the correct locations for
        the bubblebathbay IDrive audios folders
        @param epNum: The episode name  
        @param pathToFolder: The path to the folder full of wav files you want to copy over.
        @type pathToFolder: String
        @type epNum: String
        NOTE: this tool has been written around the following audio output naming convention from TOONBOOM
        ep106_sh001.wav
        ep106_sh002.wav
        ep106_sh002_A.wav
        """

        if self.epNumber.text() !=  'ep':
            for each in self.fileBoxes:
                if each.isChecked() and each.text() != 'ALL':
                    ## We will always start with a base version number of 0 as the audio files from Toonboom
                    ## Do NOT have any versioning...Therefore iteration folders from toonboom can be correctly versioned into
                    ## the publish wav folders without freaking out....
                    self.vNum = '000'
                    self.epName = str(self.epNumber.text()).lower()
                    self.shotNum = str(each.text()).split('.mov')[0].lower()
                                       
                    if sys.platform == 'win32':
                        self.shotReviewDir = 'I:/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % ( self.epName, self.shotNum)
                    else:
                        self.shotReviewDir = '/Volumes/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % ( self.epName, self.shotNum)
                        
                    self.shotReviewFileName = '%s_BOARD.v%s.mov'  %  (self.shotNum, self.vNum)
                    self.finalPath          = '%s%s' % (self.shotReviewDir, self.shotReviewFileName)       
                    
                    ## Check for folder, if it doesn't exist make it
                    if not os.path.isdir(self.shotReviewDir):
                        os.makedirs(self.shotReviewDir)
                                       
                    ## Now check for existing file, if so version it up just in case so we don't even delete.
                    if os.path.isfile(self.finalPath):
                        newVersNum =  self._versionUp(self.shotReviewDir)
                        if newVersNum <= 10:
                            self.vNum = '00%s' %newVersNum
                        elif newVersNum <= 100:
                            self.vNum = '0%s' %newVersNum
                        else:
                            self.vNum = '%s' %newVersNum
                        ## Now update the name and path vars as final.
                        self.shotReviewFileName = '%s_BOARD.v%s.mov'  %  (self.shotNum, self.vNum)
                        self.finalPath          = '%s%s' % (self.shotReviewDir, self.shotReviewFileName)
                    
                    ## Now get the original path for the audio file we are copying.
                    originalPath = '%s\\%s' % (self.sourceFolder, each.text())
                
                    ## Now perform the copy.
                    shutil.copyfile(originalPath, self.finalPath)
                    #p = subprocess.Popen(cmd, cwd=None, shell=True, bufsize=4096)
                    # Wait until process terminates
                    #while p.poll() is None:
                     #   time.sleep(0.5)
                    print 'Copied file: %s  to \t%s' % (each.text(), self.finalPath)
                    
                    if self.makeSGEntries.isChecked():
                        print 'Adding StoryBoard item to shotgun... %s: ' % self.shotReviewFileName
                        self.addStoryboardVersionToShotgun(str(self.shotReviewDir), str(self.epName), str(self.shotNum), str(self.vNum), str(self.shotReviewFileName))
            
            print 'Finished processing files'
            self.goButton.setText('COMPLETED... click to do over...')
            self.goButton.setStyleSheet('QPushButton {background-color: yellow; border: 2px solid 1 ; border-radius: 6px;}')
        else:
            self.goButton.setText('Invalid Ep Number... click to do over...')
            self.goButton.setStyleSheet('QPushButton {background-color: blue; border: 2px solid 1 ; border-radius: 6px;}')
            print 'You must set a valid episode number!!!'
Пример #23
0
    for fact_name, fact_value in fact_data.items():
        if not fact_name in facts_to_sync: continue

        fact_data = {
            'code': fact_name,
            'sg_asset': {
                'type': 'Asset',
                'id': asset['id']
            },
            'description': fact_value,
            'project': {
                'type': 'Project',
                'id': 178
            },
        }
        existing_fact = sg.find_one(
            'CustomEntity01',
            [['code', 'is', fact_name],
             ['sg_asset', 'is', {
                 'type': 'Asset',
                 'id': asset['id']
             }]], ['id'])
        if existing_fact:
            print "asset %s has existing fact %s, updating to %s" % (
                hostname, fact_name, fact_value)
            sg.update('CustomEntity01', existing_fact['id'], fact_data)
        else:
            print "asset %s creating fact %s : %s" % (hostname, fact_name,
                                                      fact_value)
            sg.create('CustomEntity01', fact_data, return_fields=['id'])
class PublishMayaAudio(QWidget):
    def __init__(self, defaultSource='I:/lsapipeline/audios/', parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Audio Publishing Tool')
        self.parent = parent
        ## Connect to shotgun

        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun.
        base_url = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'

        self.sgsrv = Shotgun(base_url=base_url,
                             script_name=script_name,
                             api_key=api_key,
                             ensure_ascii=True,
                             connect=True)

        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = {}

        ## Build the UI
        self.mainLayout = QVBoxLayout(self)

        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet(
            'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.epNumber.textChanged.connect(self.epTextChange)
        self.epNumber.setText('ep')

        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        if self.sourceFolder:
            self.sourceInput.setText(self.sourceFolder)
        self.sourceInput.textChanged.connect(partial(self.doFileCheckboxes))
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(
            partial(self._browseDialog, dest=False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)
        self.pathLayout.addWidget(self.browseButton)

        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')

        self.goButton = QPushButton('Publish Audio Files')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.goButton.clicked.connect(self._doit)

        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)

        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)

        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)

        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)

        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)

        self.fileLayout = QGridLayout(self.filesGroupBox)
        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('Publish Audio Files')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)

    def doFileCheckboxes(self, myPath=''):
        """
        Process all the folders/files found into check boxes for processing
        """
        ## try to get the epNumber from a file
        epNum = os.listdir(self.sourceInput.text())[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)

        if self.fileBoxes != {}:
            for key, var in self.fileBoxes.items():
                key.setParent(None)
                sip.delete(key)
                key = None

        self.repaint()
        self.files = []
        self.fileBoxes = {}

        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL')
        self.ALL.toggled.connect(self._toggleAll)

        self.fileBoxes[self.ALL] = None
        self.fileLayout.addWidget(self.ALL, 0, 0)

        self.colCount = 10
        r = 1
        c = 1

        ## Now process the folder and add the folders found as check boxes.
        try:
            ## Scan the entire folder structure for audio files to publish
            if self.isRootFolderThere(rootFolder=self.sourceFolder):
                print '%s found processing now...' % self.sourceFolder
                for dirname, dirnames, filenames in os.walk(self.sourceFolder):
                    if dirname.endswith('\\wav'):
                        print 'Scanning %s now..' % dirname
                        print 'Files: %s' % os.listdir(dirname)
                        getMaxFile = max(os.listdir(dirname))
                        if getMaxFile:  ## we have a folder with files in it...
                            if getMaxFile.endswith(".wav"):
                                pathToWav = os.path.join(dirname, getMaxFile)
                                self.fileCheckBox = QCheckBox(self)
                                self.fileCheckBox.setChecked(False)
                                self.fileCheckBox.setText(getMaxFile)
                                self.fileBoxes[
                                    self.fileCheckBox] = pathToWav.replace(
                                        '\\', '/')

                                if c == self.colCount:
                                    r = r + 1
                                    c = 1
                                self.fileLayout.addWidget(
                                    self.fileCheckBox, r, c)
                                c = c + 1
                                print 'Adding %s to layout now..' % pathToWav
                        else:
                            print '%s is emtpy...' % dirname
            else:
                self.files = ['No root folder found...']
        except:
            self.files = ['No wav files found...']

    def _browseDialog(self, dest=False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """

        if sys.platform == 'win32':
            print 'OPENING WIN BROWSE DIALOG NOW...'
            myPath = QFileDialog(
                self, 'rootDir',
                self.sourceFolder).getExistingDirectory().replace('\\', '/')
        else:
            print 'OPENING %s BROWSE DIALOG NOW...' % sys.platform
            myPath = QFileDialog(
                self, 'rootDir',
                self.sourceFolder).getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]

        if epNum:
            self.epNumber.setText(epNum)

        self.sourceFolder = str(myPath)

        os.system('echo epNum: %s' % self.epNumber)
        os.system('echo sourceFolder: %s' % self.sourceFolder)
        os.system('echo final myPath: %s' % myPath)
        self.sourceInput.setText(myPath)

        #self.doFileCheckboxes(myPath)

    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.wav')[0]) + 1

    def _writeMaFile(self, fileName, pathToWav, wavName, publishPath):
        ## Check the folder exists, if not make one now.
        if not os.path.isdir(os.path.dirname(self.publishPath)):
            os.makedirs(os.path.dirname(self.publishPath))

        self.header = [
            r'//Maya ASCII 2013ff10 scene',
            r'//Name: %s' % fileName,
            r'//Last modified: Tue, Jun 17, 2014 10:41:32 AM',
            r'//Codeset: 1252',
            r'requires maya "2013ff10";',
            r'requires "Mayatomr" "2013.0 - 3.10.1.11 ";',
            r'currentUnit -l centimeter -a degree -t film;',
            r'fileInfo "application" "maya";',
            r'fileInfo "product" "Maya 2013";',
            r'fileInfo "version" "2013 x64";',
            r'fileInfo "cutIdentifier" "201301140020-856945";',
            r'fileInfo "osv" "Microsoft Windows 7 Ultimate Edition, 64-bit Windows 7 Service Pack 1 (Build 7601)\n";',
        ]

        self.audioNode = [
            '\n%s' % r'createNode audio -n "%s";' % wavName.replace('.', '_'),
            '\t%s' % r'setAttr ".ef" 1000;',
            '\t%s' % r'setAttr ".se" 1000;',
            '\t%s' % r'setAttr ".f" -type "string" "%s";' % pathToWav,
        ]

        self.footer = ['\n%s' % r'// End of %s.ma' % fileName]

        ## Now write the ma file
        ## Fail if the version already exists
        pathToTextFile = publishPath
        if not os.path.isfile(pathToTextFile):
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)

            outfile.close()
        else:
            ## Remove it because we are republishing the same version again.
            os.remove(pathToTextFile)
            ## Note we can just delete this file already and move on if needed.
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)

            outfile.close()

    def _createPublish(self, publishPath, fileName, pathToWav, wavName,
                       version_number, localPath, localPathMac, wavSGName,
                       ctx):
        self.pathToWav = pathToWav
        self.publishPath = publishPath
        self.localPath = localPath
        self.localPathMac = localPathMac
        self.fileName = fileName
        self.wavName = wavName
        self.wavSGName = wavSGName
        self.version_number = version_number

        data = {
            "code": self.wavSGName,
            "description": None,
            "name": self.wavSGName,
            "project": ctx.project,
            "entity": {
                'id': self.exists['id'],
                'name': self.wavSGName,
                'type': 'CustomEntity03'
            },
            "version_number": self.version_number,
            'path_cache': self.publishPath.replace('/', '\\'),
            'published_file_type': {
                'type': 'PublishedFileType',
                'id': 1
            },
            'updated_by': {
                'type': 'HumanUser',
                'id': 53
            },
            'path': {
                'content_type': None,
                'link_type': 'local',
                'url': 'file:///%s' % self.publishPath.replace('/', '\\'),
                "local_path": self.publishPath.replace('/', '\\'),
                'local_path_linux': '',
                'local_path_mac': '%s' % self.localPathMac,
                'local_path_windows':
                '%s' % self.publishPath.replace('/', '\\'),
                'local_storage': {
                    'id': 1,
                    'name': 'primary',
                    'type': 'LocalStorage'
                },
                'name': self.fileName,
            }
        }

        self.sgsrv.create('PublishedFile', data)
        print 'Publish file created for %s' % self.wavSGName

    def _publishAudio(self):
        """
        Function to add the publish a maya audio file both making a maya file with an audio node and publishing this to shotgun as a version
        """
        for key, var in self.fileBoxes.items():
            if var:
                if key.isChecked():
                    ## Work out what we need for the creation of the ma file
                    ## and the publish for shotgun
                    self.pathToWav = var
                    if sys.platform == 'win32':
                        self.publishPath = var.replace(
                            '/publish/wav',
                            '/publish/maya').replace('.wav',
                                                     '.ma').replace('/', '\\')
                    self.localPath = self.publishPath.split('I:')[-1]
                    self.localPathMac = self.publishPath.replace(
                        'I:', '/_projects')
                    self.fileName = str(key.text()).replace('.wav', '.ma')
                    self.wavName = str(key.text())
                    self.wavSGName = str(key.text().replace('_AUD',
                                                            '').split('.')[0])
                    self.version_number = int(
                        str(key.text()).split('.')[-2].split('v')[-1])

                    ## Now register the publish with Shotgun
                    ## First find the audio on shotgun for processing.
                    self.exists = self.sgsrv.find_one(
                        'CustomEntity03',
                        filters=[["code", "is", self.wavSGName]],
                        fields=['code', 'tasks', 'id'])

                    if not self.exists:
                        print '%s has no shotgun entry! You should make sure this has been processed correctly before proceeding!!' % self.wavName

                    else:
                        ## now publish
                        tk = sgtk.sgtk_from_path("I:/lsapipeline/")
                        ctx = tk.context_from_path(self.publishPath)

                        ## For existing check
                        ## CHECK FOR EXISTING PUBLISH WITH THE SAME VERSION NUMBER!!!!
                        findExisting = self.sgsrv.find_one(
                            'PublishedFile',
                            filters=[["code", "is", self.wavSGName]],
                            fields=[
                                'code', 'id', 'version_number', 'created_at',
                                'entity'
                            ])
                        if findExisting:
                            if findExisting[
                                    'version_number'] == self.version_number:
                                print 'A PUBLISHED FILE FOR THIS VERSION ALREADY EXISTS SKIPPING! VERSION UP OR DELETE EXISTING SHOTGUN PUBLISH ENTRIES IF YOU NEED TO YOU SHOULDNT BUT YOU MIGHT!'
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName,
                                                  self.pathToWav, self.wavName,
                                                  self.publishPath)
                            else:  ## This is a new version number
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName,
                                                  self.pathToWav, self.wavName,
                                                  self.publishPath)
                                self._createPublish(
                                    publishPath=self.publishPath,
                                    fileName=self.fileName,
                                    pathToWav=self.pathToWav,
                                    wavName=self.wavName,
                                    version_number=self.version_number,
                                    localPath=self.localPath,
                                    localPathMac=self.localPathMac,
                                    wavSGName=self.wavSGName,
                                    ctx=ctx)
                        else:  ## nothing already exists so build a fresh publish
                            ## WRITE THE MA
                            ## Now write the ma file we are going to publish with the audio node created.
                            ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                            self._writeMaFile(self.fileName, self.pathToWav,
                                              self.wavName, self.publishPath)
                            self._createPublish(
                                publishPath=self.publishPath,
                                fileName=self.fileName,
                                pathToWav=self.pathToWav,
                                wavName=self.wavName,
                                version_number=self.version_number,
                                localPath=self.localPath,
                                localPathMac=self.localPathMac,
                                wavSGName=self.wavSGName,
                                ctx=ctx)

        print 'Complete'
        self.goButton.setText('COMPLETE.. click to run again')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.repaint()

    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.repaint()
        return True

    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet(
                    'QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}'
                )
                self.reply = QMessageBox.question(
                    self, 'Nope!',
                    "Nothing to transfer. Try selecting something and try again",
                    QMessageBox.Ok)
            else:
                self._publishAudio()

    def isRootFolderThere(self, rootFolder):
        """
        Method used to check if root folder is valid or not
        """
        if not os.path.isdir(rootFolder):
            print 'No such root folder found.'
            return -1
        else:
            return 1
Пример #25
0
FROM item i
JOIN product p ON i.product_id = p.product_id
WHERE product_n not like 'Unknown %'
ORDER BY item_sc DESC
''')

row = cur.fetchone()
while row:
    if not row['item_sc']:
        row = cur.fetchone()
        continue
    asset_data = transform_asset( row )

    existing_asset = sg.find_one('Asset', [['code','is',asset_data['code']]])

    if existing_asset:
        print "asset %s exists" % ( asset_data['code'] )
        sg.update('Asset', existing_asset['id'], asset_data)
    else:
        print "asset %s creating" % ( asset_data['code'] )
        try:
            sg.create('Asset', asset_data, return_fields=['id'])
            pass
        except Exception:
            pprint.pprint(row)
            pprint.pprint(asset_data)
    row = cur.fetchone()

conn.close()

        playlist_user = {'type' : 'HumanUser' , 'id' : script_user_id}
        versions_list = [ {'type' : 'Version', 'id' : x } for x in version_ids ]
        data = {
            'project': { 'type' : 'Project' , 'id' : PROJECT_ID } ,
            'code' : playlist_name ,
            'description' : playlist_description ,
            'sg_status' : PLAYLIST_STATUS ,
            'versions' : versions_list ,
            'sg_type' : PLAYLIST_TYPE ,
            'sg_script_user' : playlist_user ,
            'sg_date_and_time' : now
            }
        
        
        #Create the Playlist in Shotgun
        playlist = sg.create("Playlist",data)

        if not playlist : #error! nothing came back from SG!
            success = False

    if success: #everything has gone well and the user gets a message
                    print '</br>'
                    print "<b>Playlist successfully created</b>"
                    path_to_playlist = SERVER_PATH + '/detail/Playlist/' + str(playlist['id'])
                    #print '<a href="%s">Visit Playlist Now</a>' % path_to_playlist 
                    #print '</br>Will redirect automatically in 5 seconds'
                    print '''<a href="#" onclick="window.opener.location.href='%s'; window.opener='x';window.close();">Visit Playlist Now</a>''' % path_to_playlist
                    #print'<meta http-equiv="REFRESH" content="3;url=%s">' % path_to_playlist
                    print '</br>'

    print "</body>"
Пример #27
0
        version_list = [{'type': 'Version', 'id': x} for x in version_ids]

        data = {
            'project': {
                'type': 'Project',
                'id': PROJECT_ID
            },
            'code': playlist_name,
            'description': playlist_description,
            'sg_status': PLAYLIST_STATUS,
            'versions': version_list,
            'sg_type': PLAYLIST_TYPE,
            'sg_script_user': playlist_user,
            'sg_date_and_time': now
        }
        playlist = sg.create("Playlist", data)
        pprint(playlist)

#             entity_type = an_asset['entity']['type'] # should always be 'Shot'!
#             if entity_type == 'Shot': # we always expect a shot but OK to test
#                 shot_id = an_asset['entity']['id']
#                 linked_version = { 'type' : 'Version' , 'id' : a_version_id }
#                 data = { CURRENT_VERSION_FIELD : linked_version }
#
#                 changed_asset = sg.update("Shot", shot_id, data)
#                 print 'Shot %i Has Been Updated Successfully' % shot_id
#                 print '</br>'
#             else:
#                 success = False
#                 print('version %s is linked to something other than a shot?' % a_version_id)
#                 print '</br>'
Пример #28
0
        #print "fkey: %s fvalue: %s" % ( key, value )
        ret[key.strip()] = value.strip()
    return ret

hostname = gethostname().split('.', 1)[0]

asset = sg.find_one("Asset",[['code','is',hostname]],['id'])
if not asset:
    print "couldn't find asset"
else:
    # if we find a valid asset, sync the facts for it
    fact_data = get_fact_data()

    for fact_name,fact_value in fact_data.items():
        if not fact_name in facts_to_sync: continue

        fact_data = {
            'code': fact_name,
            'sg_asset': {'type':'Asset', 'id':asset['id']},
            'description': fact_value,
            'project': {'type':'Project', 'id':178},
        }
        existing_fact = sg.find_one('CustomEntity01', [['code','is',fact_name],['sg_asset','is',{'type':'Asset','id': asset['id']}]],['id'])
        if existing_fact:
            print "asset %s has existing fact %s, updating to %s" % ( hostname, fact_name, fact_value )
            sg.update('CustomEntity01', existing_fact['id'], fact_data)
        else:
            print "asset %s creating fact %s : %s" % ( hostname, fact_name, fact_value )
            sg.create('CustomEntity01', fact_data, return_fields=['id'])

class StoryboardFileManagement(QWidget):
    def __init__(self, defaultSource='', parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('StoryBoard File Processing')
        self.parent = parent
        ## Connect to shotgun

        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun.
        base_url = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'

        print 'Connecting to shotgun....'
        self.sgsrv = Shotgun(base_url=base_url,
                             script_name=script_name,
                             api_key=api_key,
                             ensure_ascii=True,
                             connect=True)

        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = []

        ## Build the UI
        self.mainLayout = QVBoxLayout(self)

        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet(
            'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.epNumber.textChanged.connect(self.epTextChange)
        self.epNumber.setText('ep')

        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        self.sourceInput.textChanged.connect(self.doFileCheckboxes)
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(
            partial(self._browseDialog, dest=False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)
        self.pathLayout.addWidget(self.browseButton)

        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')

        self.goButton = QPushButton(
            'Transfer SBrd Files To Episode Version Folders')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.goButton.clicked.connect(self._doit)

        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)

        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)

        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)

        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)

        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)

        self.fileLayout = QGridLayout(self.filesGroupBox)

        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText(
                'Transfer SBrd Files To Episode Version Folders')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)

    def doFileCheckboxes(self, myPath=''):
        """
        Process all the folders/files found into checkboxes for processing
        """
        ## try to get the epNumber from a file
        epNum = str(os.listdir(self.sourceInput.text())[0].split('_')[0])
        if epNum == '.DS' or epNum == '.DS_Store':
            getFiles = os.listdir(self.sourceInput.text())
            for each in getFiles:
                if ".mov" in each:
                    epNum = each.split('_')[0]
        #print 'I AM A BAD NAUGHTY VARIABLE!: %s' % epNum

        if epNum:
            self.epNumber.setText(epNum)

        if self.fileBoxes != []:
            for each in self.fileBoxes:
                each.setParent(None)
                sip.delete(each)
                each = None

        self.files = []
        self.fileBoxes = []

        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL')
        self.ALL.toggled.connect(self._toggleAll)

        self.fileBoxes.append(self.ALL)
        self.fileLayout.addWidget(self.ALL, 0, 0)

        ## Now process the folder and add the folders found as checkboxes.
        try:
            if myPath:
                if sys.platform == 'win32':
                    self.sourceFolder = myPath.replace('/', '\\')
                else:
                    self.sourceFolder = myPath
            else:
                self.sourceFolder = str(self.sourceInput.text())

            for eachFile in os.listdir(self.sourceFolder):
                if eachFile.endswith('.mov'):
                    self.files.append(eachFile)
        except:
            self.files = ['No mov files found...']

        self.colCount = 10
        r = 1
        c = 1
        for eachType in sorted(self.files):
            self.fileCheckBox = QCheckBox(self)
            self.fileCheckBox.setChecked(False)
            self.fileCheckBox.setText(eachType)
            self.fileBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.fileLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1

    def _browseDialog(self, dest=False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """
        try:
            if sys.platform == 'win32':
                myPath = QFileDialog(
                    self, 'rootDir',
                    'O:/EPISODE DELIVERY').getExistingDirectory().replace(
                        '\\', '/')
            else:
                myPath = QFileDialog(
                    self, 'rootDir',
                    '/Volumes/LemonSky/OUT TO LEMONSKY/EPISODE DELIVERY'
                ).getExistingDirectory().replace('\\', '/')
        except:
            myPath = QFileDialog(self, 'rootDir',
                                 '').getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)
        self.sourceInput.setText(myPath)
        self.sourceFolder = str(myPath)
        self.doFileCheckboxes(myPath)

    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.mov')[0]) + 1

    def addStoryboardVersionToShotgun(self, path, epName, shotName, verNum,
                                      fullVersPublishName):
        """
        Function to add the audio asset to shotgun correctly for tasks etc and the pipeline to see it
        """
        #self.shotNum = each.text().split('.mov')[0]
        #self.addStoryboardVersionToShotgun(str(self.shotReviewDir), str(self.epName), self.shotNum, self.vNum, self.shotReviewFileName)
        ## Now start processing stuff..
        self.epName = epName.lower()
        self.shotName = shotName.lower()
        self.boardName = fullVersPublishName.lower()
        self.taskName = 'StoryBoard'
        self.sg_version = verNum

        self.pathToMovie = '%s%s' % (path, self.boardName)

        ## First find it the task exists
        self.getShotTasks = self.sgsrv.find_one(
            'Shot',
            filters=[["code", "is", self.shotName]],
            fields=['id', 'tasks'])

        ## Now check and see if the task we need is there...
        self.tasks = []
        self.taskList = []
        if self.getShotTasks:
            for eachTaskDict in self.getShotTasks['tasks']:
                self.tasks.append(eachTaskDict['name'])
                self.taskList.append(eachTaskDict)

            if self.taskName not in self.tasks:
                ## Create new task for the shot
                self.myNewTask = self.sgsrv.create(
                    'Task', {
                        'project': {
                            'type': 'Project',
                            'id': 66
                        },
                        'step': {
                            'type': 'Step',
                            'id': 72,
                            'name': 'StoryBoard'
                        },
                        'content': 'StoryBoard',
                        'sg_status_list': 'apr',
                        'template_task': {
                            'type': 'Task',
                            'id': 31333
                        }
                    })
                self.taskId = int(self.myNewTask['id'])
                ## Returns {'project': {'type': 'Project', 'id': 66, 'name': 'bubblebathbay'}, 'step': {'type': 'Step', 'id': 72, 'name': 'StoryBoard'}, 'type': 'Task', 'id': 32335}

                ## Add this dict to the list of dict for updating the shot task list with.
                self.taskList.append({
                    'type': 'Task',
                    'id': self.myNewTask['id'],
                    'name': 'StoryBoard'
                })

                ## Now update the shots task list.
                self.sgsrv.update(
                    'Shot', self.getShotTasks['id'], {
                        'project': {
                            'type': 'Project',
                            'id': 66
                        },
                        'tasks': self.taskList
                    })
                print 'Successfully updated shot %s with task %s' % (
                    self.shotName, self.taskId)

                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName,
                                                       self.shotName)
                data = {
                    'project': {
                        'type': 'Project',
                        'id': 66
                    },
                    'code': self.boardName,
                    'description': 'I am not a fluffy bunny!',
                    'sg_path_to_movie': self.pathToMovie,
                    'sg_status_list': 'rev',
                    'entity': {
                        'type': 'Shot',
                        'id': self.getShotTasks['id']
                    },
                    'sg_task': {
                        'type': 'Task',
                        'id': self.taskId
                    },
                    'sg_status_list': 'vwd',
                    'user': {
                        'type': 'HumanUser',
                        'id': 53
                    }
                }
                result = self.sgsrv.create('Version', data)

                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName,
                                                          self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'],
                                            self.pathToMovie,
                                            "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)
            else:
                ## Get the story board task id
                for eachTask in self.taskList:
                    if eachTask['name'] == 'StoryBoard':
                        self.taskId = eachTask['id']

                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName,
                                                       self.shotName)
                data = {
                    'project': {
                        'type': 'Project',
                        'id': 66
                    },
                    'code': self.boardName,
                    'description': 'I am not a fluffy bunny!',
                    'sg_path_to_movie': self.pathToMovie,
                    'sg_status_list': 'rev',
                    'entity': {
                        'type': 'Shot',
                        'id': self.getShotTasks['id']
                    },
                    'sg_task': {
                        'type': 'Task',
                        'id': self.taskId
                    },
                    'sg_status_list': 'vwd',
                    'user': {
                        'type': 'HumanUser',
                        'id': 53
                    }
                }
                result = self.sgsrv.create('Version', data)

                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName,
                                                          self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'],
                                            self.pathToMovie,
                                            "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)

        else:
            print 'NO TASKS EXIST FOR %s skipping...' % self.shotName
            self._turnOffCheckBox('%s.mov' % self.shotName)

    def _turnOffCheckBox(self, shotName):
        """
        Func for turning off the uploaded movies as we progress through them so if we error out we have 
        a way to see what has been processed already
        """
        for each in self.fileBoxes:
            if str(each.text()) == shotName:
                each.setChecked(False)
                self.repaint()

    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.repaint()
        return True

    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet(
                    'QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}'
                )
                self.reply = QMessageBox.question(
                    self, 'Nope!',
                    "Nothing to transfer. Try selecting something and try again",
                    QMessageBox.Ok)
            else:
                self.processStoryBoardFolder()

    def processStoryBoardFolder(self):
        """
        Function to copy over all the audio files from a single output folder into the correct locations for
        the bubblebathbay IDrive audios folders
        @param epNum: The episode name  
        @param pathToFolder: The path to the folder full of wav files you want to copy over.
        @type pathToFolder: String
        @type epNum: String
        NOTE: this tool has been written around the following audio output naming convention from TOONBOOM
        ep106_sh001.wav
        ep106_sh002.wav
        ep106_sh002_A.wav
        """

        if self.epNumber.text() != 'ep':
            for each in self.fileBoxes:
                if each.isChecked() and each.text() != 'ALL':
                    ## We will always start with a base version number of 0 as the audio files from Toonboom
                    ## Do NOT have any versioning...Therefore iteration folders from toonboom can be correctly versioned into
                    ## the publish wav folders without freaking out....
                    self.vNum = '000'
                    self.epName = str(self.epNumber.text()).lower()
                    self.shotNum = str(each.text()).split('.mov')[0].lower()

                    if sys.platform == 'win32':
                        self.shotReviewDir = 'I:/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % (
                            self.epName, self.shotNum)
                    else:
                        self.shotReviewDir = '/Volumes/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % (
                            self.epName, self.shotNum)

                    self.shotReviewFileName = '%s_BOARD.v%s.mov' % (
                        self.shotNum, self.vNum)
                    self.finalPath = '%s%s' % (self.shotReviewDir,
                                               self.shotReviewFileName)

                    ## Check for folder, if it doesn't exist make it
                    if not os.path.isdir(self.shotReviewDir):
                        os.makedirs(self.shotReviewDir)

                    ## Now check for existing file, if so version it up just in case so we don't even delete.
                    if os.path.isfile(self.finalPath):
                        newVersNum = self._versionUp(self.shotReviewDir)
                        if newVersNum <= 10:
                            self.vNum = '00%s' % newVersNum
                        elif newVersNum <= 100:
                            self.vNum = '0%s' % newVersNum
                        else:
                            self.vNum = '%s' % newVersNum
                        ## Now update the name and path vars as final.
                        self.shotReviewFileName = '%s_BOARD.v%s.mov' % (
                            self.shotNum, self.vNum)
                        self.finalPath = '%s%s' % (self.shotReviewDir,
                                                   self.shotReviewFileName)

                    ## Now get the original path for the audio file we are copying.
                    originalPath = '%s\\%s' % (self.sourceFolder, each.text())

                    ## Now perform the copy.
                    shutil.copyfile(originalPath, self.finalPath)
                    #p = subprocess.Popen(cmd, cwd=None, shell=True, bufsize=4096)
                    # Wait until process terminates
                    #while p.poll() is None:
                    #   time.sleep(0.5)
                    print 'Copied file: %s  to \t%s' % (each.text(),
                                                        self.finalPath)

                    if self.makeSGEntries.isChecked():
                        print 'Adding StoryBoard item to shotgun... %s: ' % self.shotReviewFileName
                        self.addStoryboardVersionToShotgun(
                            str(self.shotReviewDir), str(self.epName),
                            str(self.shotNum), str(self.vNum),
                            str(self.shotReviewFileName))

            print 'Finished processing files'
            self.goButton.setText('COMPLETED... click to do over...')
            self.goButton.setStyleSheet(
                'QPushButton {background-color: yellow; border: 2px solid 1 ; border-radius: 6px;}'
            )
        else:
            self.goButton.setText('Invalid Ep Number... click to do over...')
            self.goButton.setStyleSheet(
                'QPushButton {background-color: blue; border: 2px solid 1 ; border-radius: 6px;}'
            )
            print 'You must set a valid episode number!!!'
'''

from shotgun_api3 import Shotgun
from pprint import pprint

SERVER_PATH = 'http://****.shotgunstudio.com' #your server path here
SCRIPT_USER = '******' #your script name 
SCRIPT_KEY =  '*********' #your key here
URL_OF_CGI = "http://www.YOURURL.***/cgi-bin/set_current_version_posthandler_cgi.py"
title = "Set As Current Version"
entity_type = "Version"
selection_required = True



# initiate a shotgun API instance
sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

#define the action menu item
data = {
  "title": title,
  "url": URL_OF_CGI,
  "list_order": 1,
  "entity_type": entity_type,
  "selection_required": selection_required, 

}

#Create the menu item
menu_item = sg.create("ActionMenuItem", data)
pprint(menu_item) # keep the output in case you need to delete the menu later!
Пример #31
0
class ShotgunDelivery(object):
    def __init__(self, **kwargs):
        self.contents_folder = kwargs['contents_folder']
        self.linux_username = kwargs['linux_username']
        self.job_num = kwargs['job_num']
        self.job_name = kwargs['job_name']
        self.locate_user_shotgun_id = kwargs['locate_user_shotgun_id']
        self.in_or_out = kwargs['in_or_out']

        if self.in_or_out == 'in':
            self.ingested_files = kwargs['ingested_files']

        proxy = '###'
        server_path = '###'
        convert_datetimes_to_utc = False

        self.sg = Shotgun(server_path, kwargs['script_name'],
                          kwargs['script_key'], convert_datetimes_to_utc,
                          proxy)

        self.contents = ''
        self.title = ''

    def create_shotgun_delivery(self):
        if self.locate_user_shotgun_id:
            self.find_user_shotgun_id()
        else:
            self.known_user_shotgun_id()
        self.set_users_shotgun_id()
        self.generate_all_jobs_shotgun_details()
        self.generate_contents_and_title_fields()
        self.populate_delivery_fields()
        self.build_shotgun_delivery()
        self.link_shotgun_delivery()

    def find_user_shotgun_id(self):
        newbee = '\nHmm, you must be new here.' \
                 '\nGo to the shotgun website.' \
                 '\nClick on the search bar in the top right.' \
                 '\nSearch for your name.' \
                 '\nClick on person info.' \
                 '\nSee the 2 or 3 digit Id number?' \
                 '\nEnter that here* '
        for letter in newbee:
            if letter != '*':
                sys.stdout.write(letter)
                sys.stdout.flush()
                time.sleep(0.05)
            else:
                sys.stdout.write(': ')
                sys.stdout.flush()
                self.shotgun_user_id = raw_input()
                while len(shotgun_user_id) != 2 and len(shotgun_user_id) != 3:
                    self.shotgun_user_id = raw_input('\nThat\'s not a valid Id ' \
                                                     'number.\nIt is a 2 or 3 digit number ' \
                                                     'probably 3 in your case.\nId: ')
        time.sleep(1)

    def known_user_shotgun_id(self):
        shotgun_user_ids = {'###': ''}

        match = False
        for shotgun_user, shotgun_user_id in shotgun_user_ids.iteritems():
            if shotgun_user == self.linux_username:
                self.shotgun_user_id = shotgun_user_id
                match = True

        if not match:
            self.shotgun_user_id = int(raw_input('\nEnter your shotgun user ID ' \
                                                 '(run script with -id to ' \
                                                 'find what it is): '))

    def set_users_shotgun_id(self):
        if self.locate_user_shotgun_id:
            self.find_user_shotgun_id()
        else:
            self.known_user_shotgun_id()

    def generate_all_jobs_shotgun_details(self):
        self.all_job_details = {
            'job_name': [
                '###', '###', '###', '###', '###', '###', '###', '###', '###',
                '###'
            ],
            'project_id': [
                '###',
                '###',
                '###',
                '###',
                '###',
                '###',
                '###',
                '###',
                '###',
            ],
            'client_id':
            ['###', '###', '###', '###', '###', '###', '###', '###', '###'],
            'delivery_method': [
                '###', '###', '###', '###', '###', '###', '###', '###', '###',
                '###'
            ]
        }

    def generate_contents_and_title_fields(self):
        if self.in_or_out == 'in':
            for the_file in self.ingested_files:
                self.contents += str(subprocess.Popen('ls -1 -R ' + \
                                     self.contents_folder + the_file,
                                     stdout=subprocess.PIPE,
                                     shell=True).communicate()[0])
                self.title += the_file + ', '

        if self.in_or_out == 'out':
            self.contents = str(
                subprocess.Popen('ls -1 -R ' + self.contents_folder,
                                 stdout=subprocess.PIPE,
                                 shell=True).communicate()[0])
            split_contents_folder = self.contents_folder.split('/')
            self.title = split_contents_folder[-1]
            if not self.title:
                self.title = split_contents_folder[-2]

    def populate_delivery_fields(self):
        todays_date = datetime.datetime.now()
        self.shotgun_job_details = {
            'job_name':
            self.all_job_details['job_name'][self.job_num],
            'title':
            self.title,
            'date':
            todays_date.strftime('%Y-%m-%d'),
            'project_id':
            self.all_job_details['project_id'][self.job_num],
            'to_client': {
                'type': 'ClientUser',
                'id': self.all_job_details['client_id'][self.job_num]
            },
            'delivery_method':
            self.all_job_details['delivery_method'][self.job_num],
            'delivery_template': {
                'type': 'TaskTemplate',
                'id': 8
            },
            'contents':
            self.contents
        }

        if self.in_or_out == 'in':
            self.shotgun_job_details['from_user'] = {
                'type': 'ClientUser',
                'id': self.all_job_details['client_id'][self.job_num]
            }
            self.shotgun_job_details['to_user'] = {
                'type': 'HumanUser',
                'id': int(self.shotgun_user_id)
            }
            self.shotgun_job_details['status'] = 'recd'
            self.shotgun_job_details['delivery_type'] = 'IN'
        elif self.in_or_out == 'out':
            self.shotgun_job_details['from_user'] = {
                'type': 'HumanUser',
                'id': int(self.shotgun_user_id)
            }
            self.shotgun_job_details['to_user'] = {
                'type': 'ClientUser',
                'id': self.all_job_details['client_id'][self.job_num]
            }
            self.shotgun_job_details['status'] = 'dlvr'
            self.shotgun_job_details['delivery_type'] = 'OUT'

    def build_shotgun_delivery(self):
        self.delivery_data = {
            'project': {
                "type": "Project",
                "id": self.shotgun_job_details['project_id']
            },
            'title': self.shotgun_job_details['title'],
            'sg_from': self.shotgun_job_details['from_user'],
            'addressings_to': [self.shotgun_job_details['to_user']],
            #'addressings_cc': [cc_user],
            'sg_delivery_method': self.shotgun_job_details['delivery_method'],
            'sg_contents': self.shotgun_job_details['contents'],
            'sg_status_list': self.shotgun_job_details['status'],
            'sg_delivery_type': self.shotgun_job_details['delivery_type'],
            'task_template': self.shotgun_job_details['delivery_template']
        }

        if self.in_or_out == 'in':
            desc = 'Recevied '
            self.delivery_data['sg_received_date'] = self.shotgun_job_details[
                'date']
        elif self.in_or_out == 'out':
            desc = 'Delivered '
            self.delivery_data['sg_due_date'] = self.shotgun_job_details[
                'date']

        self.delivery_data['description'] = '%s %s' \
                                            % (desc,
                                            self.shotgun_job_details['title'])

    def link_shotgun_delivery(self):
        create_del = self.sg.create("Delivery", self.delivery_data)

        link_file_data = {
            'this_file': {
                'local_path': self.contents_folder,
                'name': self.shotgun_job_details['title'],
            },
            'attachment_links': [{
                'type': 'Delivery',
                'id': create_del['id']
            }],
            'project': {
                'type': 'Project',
                'id': self.shotgun_job_details['project_id']
            }
        }

        self.sg.create('Attachment', link_file_data)
        print '\nShotgun delivery created.\n'
Пример #32
0
    p.prod_cls_n
FROM item i
JOIN product p ON i.product_id = p.product_id
WHERE product_n not like 'Unknown %'
ORDER BY item_sc DESC
''')

row = cur.fetchone()
while row:
    if not row['item_sc']:
        row = cur.fetchone()
        continue
    asset_data = transform_asset(row)

    existing_asset = sg.find_one('Asset', [['code', 'is', asset_data['code']]])

    if existing_asset:
        print "asset %s exists" % (asset_data['code'])
        sg.update('Asset', existing_asset['id'], asset_data)
    else:
        print "asset %s creating" % (asset_data['code'])
        try:
            sg.create('Asset', asset_data, return_fields=['id'])
            pass
        except Exception:
            pprint.pprint(row)
            pprint.pprint(asset_data)
    row = cur.fetchone()

conn.close()
Пример #33
0
    },
    'description': description,
    'sg_task': {
        'id': 2252,
        'type': 'Task'
    },
    'user': {
        'id': 92,
        'type': 'HumanUser'
    },
    'sg_status_list': 'rev',
    'project': {
        'id': 110,
        'type': 'Project'
    }
}
try:
    result = sg.create("Version", data)
    print "Creating new version of the %s %s" % (typeToUpload, ID)
    #file_path = 'C:\\Users\\Nacho\\Pictures\\turtle.jpg'
    print "The new version have the ID: %s" % sg.upload(
        "Version",
        result["id"],
        file_path,
        field_name="sg_uploaded_movie",
        display_name="Media")
except Exception as e:
    print e
print "Version added Succesfully. Bye!"
time.sleep(5)
Пример #34
0
class studioShotgun(object):
    def __init__(self, path, name, key, project):
        self.SERVER_PATH = path
        self.SCRIPT_NAME = name
        self.SCRIPT_KEY = key
        self.project_id = project
        self.sg = Shotgun(self.SERVER_PATH, self.SCRIPT_NAME, self.SCRIPT_KEY)

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectId(self, newId):
        self.project_id = newId

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectName(self, name):
        newId = 0
        projects = self.sg.find('Project', [], ['name'])
        for project in projects:
            if project['name'] == name:
                newId = project['id']

        self.project_id = newId

    #----------------------------------------------------------------------
    ## find asset by name
    def findAssetByName(self, name):
        fields = ['id', 'code', 'sg_asset_type', 'tasks']
        filters = [[
            'project', 'is', {
                'type': 'Project',
                'id': self.project_id
            }
        ], ['code', 'is', name]]

        result = self.sg.find('Asset', filters, fields)

        return result

    #----------------------------------------------------------------------
    ## find shot by name
    def findShotByName(self, episode, shot):
        fields = ['id', 'code', 'sg_asset_type', 'tasks', 'sg_sequence']
        filters = [[
            'project', 'is', {
                'type': 'Project',
                'id': self.project_id
            }
        ], ['code', 'is', shot]]

        result = self.sg.find('Shot', filters, fields)

        for x in result:
            name = x['sg_sequence']['name'].split('_')[0]
            if name == episode:
                return x

        return []

    #----------------------------------------------------------------------
    ## upload thumbnail to asset
    def uploadThumbnail(self, asset, thumbnail):
        upload = 0
        asset = self.findAssetByName(asset)
        if asset:
            upload = self.sg.upload_thumbnail("Asset", asset[0]['id'],
                                              thumbnail)

        return upload

    #----------------------------------------------------------------------
    ## create new asset
    def createAsset(self,
                    asset,
                    assetType,
                    template,
                    assetFile='',
                    description=''):
        ## find asset
        asset = self.findAssetByName(asset)

        if not asset:
            ## create asset + task template
            filters = [['code', 'is', template]]
            template = self.sg.find_one('TaskTemplate', filters)

            data = {
                'project': {
                    'type': 'Project',
                    'id': self.project_id
                },
                'code': asset,
                'description': description,
                'sg_asset_type': assetType,
                'sg_url_perforce': assetFile,
                'task_template': template
            }

            asset = self.sg.create('Asset', data)

        return asset

    #----------------------------------------------------------------------
    ## update file path in asset
    def updateAssetFilePath(self, asset, filename):
        asset = self.findAssetByName(asset)

        data = {'sg_url_perforce': filename}
        asset = self.sg.update("Asset", asset[0]['id'], data)

        return asset

    #----------------------------------------------------------------------
    ## create new version
    def createVersion(self, shotId, taskId, userId, filename, comment=''):
        curTime = datetime.now().strftime('%Y.%m.%d_%H.%M')
        fname = str(filename.split('/')[-1].split('.')[0]) + '_' + curTime

        data = {
            'project': {
                'type': 'Project',
                'id': self.project_id
            },
            'code': fname,
            'description': comment,
            'sg_status_list': 'rev',
            'entity': {
                'type': 'Shot',
                'id': shotId
            },
            'sg_task': {
                'type': 'Task',
                'id': taskId
            },
            'user': {
                'type': 'HumanUser',
                'id': userId
            }
        }

        result = self.sg.create('Version', data)

        upload = self.sg.upload('Version', result['id'], filename,
                                'sg_uploaded_movie')

        return [result, upload]

    #----------------------------------------------------------------------
    ## get user data from shotgum
    def getUserData(self, user):
        filters = [['login', 'is', user]]
        user = self.sg.find('HumanUser', filters)

        if user:
            return user[0]
        else:
            return []

    #----------------------------------------------------------------------
    ## get all user from project
    def getAllUsers(self):
        fields = ['id', 'login', 'name', 'projects', 'department']
        filters = [[
            'projects', 'is', {
                'type': 'Project',
                'id': self.project_id
            }
        ]]
        users = self.sg.find('HumanUser', filters, fields)

        return users
Пример #35
0

Author Tom Stratton / tom at tomstratton dot net  (code mostly stolen from SG docs)
'''

from shotgun_api3 import Shotgun
from pprint import pprint

SERVER_PATH = 'http://****.shotgunstudio.com'  #your server path here
SCRIPT_USER = '******'  #your script name
SCRIPT_KEY = '*********'  #your key here
URL_OF_CGI = "http://www.YOURURL.***/cgi-bin/set_current_version_posthandler_cgi.py"
title = "Set As Current Version"
entity_type = "Version"
selection_required = True

# initiate a shotgun API instance
sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

#define the action menu item
data = {
    "title": title,
    "url": URL_OF_CGI,
    "list_order": 1,
    "entity_type": entity_type,
    "selection_required": selection_required,
}

#Create the menu item
menu_item = sg.create("ActionMenuItem", data)
pprint(menu_item)  # keep the output in case you need to delete the menu later!
    def _moveFilesToPublish(self):
        base_url = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'playBlastPublisher'
        api_key = '718daf67bfd2c7e974f24e7cbd55b86bb101c4e5618e6d5468bc4145840e4558'

        sgsrv = Shotgun(base_url=base_url,
                        script_name=script_name,
                        api_key=api_key,
                        ensure_ascii=True,
                        connect=True)
        selectedShots = [
            item.text(0) for item in self.treeWidgetItems if item.checkState(0)
        ]
        if selectedShots:
            for each in selectedShots:
                episode = each.split('sh')[0]
                shotName = '%s_sh%s' % (each.split('sh')[0],
                                        each.split('sh')[1].split('Lay')[0])
                self.publishPath = self.publishingPath(episode, shotName)
                for root, dirs, files in os.walk(self.shFldPath):
                    for fl in sorted(files):
                        ext = os.path.splitext(fl)[-1]
                        if (fl.endswith('.mov') and
                            (fl
                             == '%s.mov' % each)) or (fl.endswith('.MOV') and
                                                      (fl == "%s.MOV" % each)):
                            srcPath = os.path.join(root, fl)
                            #                             print srcPath, ext
                            self.playblastName = fl
                            while os.path.exists(
                                    os.path.join(self.publishPath, fl)):
                                allFiles = os.listdir(self.publishPath)
                                publishFiles = []
                                if allFiles:
                                    for allFile in allFiles:
                                        if allFile.endswith(ext):
                                            print allFile
                                            publishFiles.append(allFile)
                                versionNumber = int(
                                    sorted(publishFiles)[-1].split('.v')
                                    [1].split(ext)[0])
                                versionNumber += 1
                                if versionNumber < 10:
                                    publishFileName = '%sLayout.v%03d%s' % (
                                        shotName.replace(
                                            '_', ''), versionNumber, ext)
                                    self.publishPath = os.path.join(
                                        self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(
                                        self.publishPath)
                                else:
                                    publishFileName = '%sLayout.v%02d%s' % (
                                        shotName.replace(
                                            '_', ''), versionNumber, ext)
                                    self.publishPath = os.path.join(
                                        self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(
                                        self.publishPath)

                            shutil.copy2(srcPath, self.publishPath)

                            publishMovPath = os.path.join(
                                self.publishingPath(episode, shotName),
                                self.playblastName)

                            getShotTasks = sgsrv.find_one(
                                'Shot',
                                filters=[["code", "is", shotName]],
                                fields=['id', 'tasks'])

                            for key, values in getShotTasks.iteritems():
                                if key == 'tasks':
                                    for value in values:
                                        if value['name'] == 'Layout':
                                            self.taskId = value['id']
                            if self.publishPath.endswith('review'):
                                self.publishPath = os.path.join(
                                    self.publishPath, fl)
                                self.playblastName = fl
                            data = {
                                'project': {
                                    'type': 'Project',
                                    'id': 66
                                },
                                'code': self.playblastName,
                                'description': 'Layout playblast published',
                                'sg_path_to_movie': publishMovPath,
                                'sg_status_list': 'rev',
                                'entity': {
                                    'type': 'Shot',
                                    'id': getShotTasks['id']
                                },
                                'sg_task': {
                                    'type': 'Task',
                                    'id': self.taskId
                                },
                                'user': {
                                    'type': 'HumanUser',
                                    'id': 92
                                }
                            }
                            result = sgsrv.create('Version', data)
                            result2 = sgsrv.upload("Version", result['id'],
                                                   publishMovPath,
                                                   "sg_uploaded_movie")
                print "Done"
Пример #37
0
    people = sg.find("HumanUser", [['email', 'is', msg_dict["from"]]],
                     ['id', 'name'])
    if len(people) < 1:
        print "couldn't find user"
    else:
        # if we find a valid user, create a ticket for them
        user = people[0]
        ticket_data = {
            'created_by': {
                'type': 'HumanUser',
                'id': user['id']
            },
            'addressings_to': [{
                'type': 'Group',
                'id': 5
            }],
            'title': msg_dict['subject'],
            'description': msg_dict['body'],
            'project': {
                'type': 'Project',
                'id': 178
            },
        }
        sg.create('Ticket', ticket_data, return_fields=['id'])

        # if we made it this far the e-mail was processed, now delete it
        M.store(num, '+FLAGS', '\\Deleted')

M.close()
M.logout()
Пример #38
0
class ShotgunUtils():
    '''
    a light version of the shotgun utils class to connect and update shotgun task for external artist
    '''
    def __init__(self):
        '''
        creates the connection to the shotgun site by api
        '''
        '''   shotgun conection '''
        SERVER_PATH = "https://hcpstudio.shotgunstudio.com"
        SCRIPT_NAME = 'Tracker'
        SCRIPT_KEY = '99b5c166044037cc2d04646b1dfd58b2f44e8a146b710b425b8f561f2a21e49d'

        self.sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
        self.userId = None
        self.userDic = {}
        self.tasks = None
        self.projectPath = None

    def getsgParameters(self, sgType, parameter=None):
        schema = self.sg.schema_field_read(sgType, parameter)
        print schema

    def getUserId(self, userName):

        filters = [['name', 'is', userName]]
        field = ['id', 'name', 'sg_projectpath', 'sg_keyword', 'login']

        user = self.sg.find_one('HumanUser', filters, field)

        if user:
            self.userId = user['id']
            self.projectPath = user['sg_projectpath']
            self.userDic = user

            return user['id']

        else:
            print "no {0} User found ".format(userName)
            return None

    def taskByUser(self):

        if not self.userId == None:

            filter = [[
                'task_assignees', 'is', {
                    'type': 'HumanUser',
                    'id': self.userId
                }
            ], ['sg_status_list', 'is_not', 'fin'],
                      ['sg_status_list', 'is_not', 'apr'],
                      ['sg_status_list', 'is_not', 'cmpt']]

            fields = [
                'id', 'content', 'sg_status_list', 'start_date', 'due_date',
                'sg_complexity', 'sg_priority_1', 'sg_note', 'project',
                'entity', 'sg_digitalmedia', 'sg_displayname'
            ]

            order = [{
                'field_name': 'due_date',
                'direction': 'asc'
            }, {
                'field_name': 'sg_priority_1',
                'direction': 'asc'
            }, {
                'field_name': 'sg_complexity',
                'direction': 'desc'
            }]

            taskList = self.sg.find('Task', filter, fields, order)

            if taskList:
                self.tasks = taskList
                return taskList

            else:

                self.tasks = []

                print "no task Asigned to: ", self.userId
                return taskList

        else:
            taskList = []

            print "no Id found"
            return taskList

    def getTaskById(self, taskId):

        filter = [['id', 'is', taskId]]

        fields = [
            'id', 'content', 'sg_status_list', 'start_date', 'due_date',
            'sg_complexity', 'sg_priority_1', 'sg_note', 'project', 'entity',
            'sg_digitalmedia', 'sg_displayname'
        ]

        task = self.sg.find_one('Task', filter, fields)

        if task:
            return task

        else:
            print 'no task found'
            return None

    def updateStatusFromUser(self, taskId, status):

        task = self.getTaskById(taskId)

        if task:

            project = task['project']
            sgStatus = status

            data = {'project': project, 'sg_status_list': sgStatus}

            self.sg.update('Task', taskId, data)
            return 1

        else:
            print 'No task by this id'
            return None

    def updateProjectPath(self, projectPath):

        data = {'sg_projectpath': projectPath}

        self.sg.update('HumanUser', self.userId, data)

    def getNotes(self, sgTaskId):

        task = self.getTaskById(sgTaskId)
        if task:
            filters = [['tasks', 'is', task]]
            fields = ['content', 'created_at', 'user', 'addressings_to']
            order = [{'field_name': 'created_at', 'direction': 'asc'}]

            notes = self.sg.find('Note', filters, fields, order)

            return notes

        else:
            print 'no Task'
            return None

    def createNote(self, taskId, content):

        task = self.getTaskById(taskId)

        if task:

            data = {
                'project': task['project'],
                'content': content,
                'tasks': [task],
                'user': self.userDic,
                'subject': 'Note'
            }

            note = self.sg.create('Note', data)
            return note['id']

        else:
            return None

    def uploadAttachment(self, taskId, filePath, tag):

        task = self.getTaskById(taskId)

        if task:

            entity = task['entity']
            if entity:

                entityType = entity['type']
                entityId = entity['id']

                uploadedfile = self.sg.upload(entityType, entityId, filePath)

                if uploadedfile:
                    data = {'sg_type': tag, 'sg_taskid': taskId}
                    self.sg.update('Attachment', uploadedfile, data)
                    return uploadedfile
                else:
                    return None
            else:
                print 'no entity set'
                return None

    def downloadAttachment(self, taskId, downloadPath, parent=None):

        filters = [['sg_taskid', 'is', taskId], ['sg_type', 'is', 'REFERENCE']]
        fields = ['id', 'attachment_links', 'filename', 'created_at']
        attachments = self.sg.find('Attachment', filters, fields)

        if attachments:
            progressBar = QtGui.QProgressBar(parent)
            progressBar.show()
            size = len(attachments)

            for x, attach in enumerate(attachments):

                extension = path.splitext(attach['filename'])
                dt = attach['created_at'].strftime("%Y_%m_%d_%H-%M-%S")
                name = attach['attachment_links'][0]['id']

                namePadded = '{0}_{3}.{1:04d}{2}'.format(
                    name, x, extension[-1], dt)

                fullPath = path.join(downloadPath, namePadded)

                dwFile = self.sg.download_attachment(attach, fullPath,
                                                     attach['id'])

                progressBar.setValue(((x + 1) / size) * 100)

            progressBar.close()
            return attachments
        else:
            return None

    def uploadReference(self, entityType, entityId, filePath, tag, taskId):

        uploadedfile = self.sg.upload(entityType, entityId, filePath)

        if uploadedfile:
            data = {
                'sg_type': tag,
                'sg_type': 'REFERENCE',
                'sg_taskid': taskId
            }
            self.sg.update('Attachment', uploadedfile, data)

            return uploadedfile

        else:
            return None
Пример #39
0
    'project': {'type':'Project','id':146}
    }


asset = sg.find_one("Asset", [["code","is","afficheOeuvre"]], ["code"])

sg_user = sg.find_one('HumanUser', [['login', 'is', "houdon.thibault"]])
data = {
    'project': {'type':'Project','id':project_id},
    'note_links': [asset],
    'user': sg_user,
    'content':'Test',
    'subject':"Thibault's Note on afficheOeuvre"
    }

sg.create("Note", data)

#version = sg.create("Version", data)


#sg.upload("Version", version["id"], "Z:/Groupes-cours/NAND999-A15-N01/Nature/assets/mod/.thumb/blocCadre_01_full.jpg", "image", "Test")


# data = {
#     'project': {'type':'Project','id':project_id},
#     'code':'Test',
#     'description':'Finir le modeling du lion',
#     'sg_status_list':'ip',
#     'shots':xxxx_shot
#     }
Пример #40
0
efilenames = {}
for efile in efiles:
    efilenames[efile['attachment_links'][0]['name']] = efile['id']
print efilenames
enames = {}
for eper in epers:
    enames[eper['code']] = eper
print enames

pers = glob('pers/*.json')
for per in pers:
    with open(per) as json_data:
        temp = json.load(json_data)
    json_data.close()
    data = {
        'code': temp['name'],
        'description': temp['desc'],
        'sg_arcana': temp['arcana'],
        'sg_level': (int)(temp['level']),
        'sg_json': None
    }
    if temp['name'] not in enames:
        data['project'] = {'type': 'Project', 'id': 70}
        id = sg.create('CustomEntity07', data, ['id'])['id']
    else:
        id = sg.update('CustomEntity07', enames[temp['name']]['id'],
                       data)['id']
        if temp['name'] in efilenames:
            sg.delete('Attachment', efilenames[temp['name']])
    sg.upload('CustomEntity07', id, per, 'sg_json')
Пример #41
0
from tests import connect

from shotgun_api3 import Shotgun

if True:
    sg = connect()
else:
    sg = Shotgun('http://127.0.0.1:8020', 'name', 'key')

print sg.server_info

proj = sg.create('Project', {'name': 'Mock Project Test'})
seq = sg.create('Sequence', {'code': 'AA', 'project': proj})
shot = sg.create('Shot', {'code': 'AA_001', 'sg_sequence': seq})

print proj
print seq
print shot
#
# print sg.find('Project', [('id', 'is_not', 0)], ['name'], order=[
#     {'field_name': 'id', 'direction': 'asc'},
# ])

print sg._call_rpc('count', None)
exit()

print sg.create('Project', {'name': 'Test Project'})
print sg.count()
print sg.find_one('Project', [],
                  order=[
                      {