def launch(self, event): if "values" in event["data"]: # Do something with the values or return a new form. values = event["data"]["values"] success = True msg = "Asset deleted." # deleting all assets if values["asset"] == "all": entity = None try: entity = ftrack.Project( event["data"]["selection"][0]["entityId"]) except: entity = ftrack.Task( event["data"]["selection"][0]["entityId"]) for asset in entity.getAssets(): asset.delete() return {"success": success, "message": "All assets deleted."} asset = ftrack.Asset(values["asset"]) asset.delete() return {"success": success, "message": msg} data = [] entity = None try: entity = ftrack.Project(event["data"]["selection"][0]["entityId"]) except: entity = ftrack.Task(event["data"]["selection"][0]["entityId"]) for asset in entity.getAssets(): if asset.getName(): name = "{0} ({1})".format(asset.getName(), asset.getType().getName()) data.append({"label": name, "value": asset.getId()}) else: data.append({"label": "None", "value": asset.getId()}) if len(data) > 1: data.append({"label": "All", "value": "all"}) return { "items": [{ "label": "Asset", "type": "enumerator", "name": "asset", "data": data }] }
def createNotes(self, selection, text, category): entityCount = len(selection) logging.info('Creating notes on {0} entities'.format(entityCount)) job = ftrack.createJob( 'Creating notes ({0} of {1})'.format(1, entityCount), 'running' ) try: for index, item in enumerate(selection, start=1): entityType = item['entityType'] entityId = item['entityId'] entity = None if index != 1: job.setDescription('Creating notes ({0} of {1})'.format(index, entityCount)) if entityType == 'show': entity = ftrack.Project(entityId) elif entityType == 'task': entity = ftrack.Task(entityId) elif entityType == 'assetversion': entity = ftrack.AssetVersion(entityId) if not entity: logging.warning( u'Entity ({0}, {1}) not a valid type, skipping..' .format(entityId, entityType) ) entity.createNote(text, category) except Exception: job.setStatus('failed') logging.info('Note creation completed.') job.setStatus('done')
def process(self, instance, context): # skipping the call up project ftrack_data = instance.context.data('ftrackData') if ftrack_data['Project']['code'] == 'the_call_up': return # validate frame range if 'Shot' in ftrack_data: task = ftrack.Task(ftrack_data['Task']['id']) project = task.getParents()[-1] shot = task.getParent() local_first_frame = render_globals.startFrame.get() online_first_frame = shot.getFrameStart() msg = 'First frame is incorrect.' msg += '\n\nLocal last frame: %s' % local_first_frame msg += '\n\nOnline last frame: %s' % online_first_frame assert local_first_frame == online_first_frame, msg local_last_frame = render_globals.endFrame.get() online_last_frame = shot.getFrameEnd() msg = 'Last frame is incorrect.' msg += '\n\nLocal last frame: %s' % local_last_frame msg += '\n\nOnline last frame: %s' % online_last_frame assert local_last_frame == online_last_frame, msg
def callback(event): """ This plugin creates a template folder structure on disk. """ for entity in event['data'].get('entities', []): if entity.get('entityType') == 'task' and entity['action'] == 'add': task = ftrack.Task(id=entity['entityId']) user = ftrack.User(id=event['source']['user']['id']) taskName = task.getName().lower() if task.getObjectType() == 'Task': project = task.getProject() projFolder = getProjectFolder(project) shotName = task.getParent().getName() if task.getParent().get('objecttypename') == 'Asset Build': taskFolder = createAssetFolders(task, projFolder) shotName = '{0}_{1}'.format(shotName, taskName) else: shotsFolder = os.path.join(projFolder, 'shots') shotFolder = getShotFolder(task) if shotFolder == '': return sceneFolder = os.path.join(shotsFolder, shotFolder, 'scene') taskFolder = os.path.join(sceneFolder, taskName) if not os.path.exists(taskFolder): os.makedirs(taskFolder) try: os.chmod(taskFolder, 0777) except: print "could not change directory permission for %s" % taskFolder templateFolder = os.path.join(projFolder, 'template_files') createTemplateFiles(templateFolder, task, taskFolder, shotName, user) syncToCpt(taskFolder.rstrip('/'))
def get_path(self, instance): ftrack_data = instance.context.data('ftrackData') parent_name = None try: parent_name = ftrack_data['Shot']['name'] except: parent_name = ftrack_data['Asset_Build']['name'].replace(' ', '_') project = ftrack.Project(id=ftrack_data['Project']['id']) root = project.getRoot() file_name = os.path.basename(instance.context.data('currentFile')) file_name = os.path.splitext(file_name)[0] task_name = ftrack_data['Task']['name'].replace(' ', '_').lower() version_number = instance.context.data('version') version_name = 'v%s' % (str(version_number).zfill(3)) filename = '.'.join([parent_name, task_name, version_name, '%04d']) path = [root, 'renders', 'img_sequences'] task = ftrack.Task(ftrack_data['Task']['id']) for p in reversed(task.getParents()[:-1]): path.append(p.getName()) path.append(task_name) path.append(version_name) path.append(str(instance)) path.append(filename) return os.path.join(*path).replace('\\', '/')
def publishImage(self, filename, taskid, shot, job): asset = self.getAsset(shot, 'ReviewAsset') status = ftrack.Status('Pending Internal Review') meta = { 'source_file': filename } version = asset.createVersion('Upload for Internal Review', taskid) location = ftrack.Location('ftrack.server') try: component = version.createComponent(name='ftrackreview-image', path=filename, location=location) metaData = json.dumps({ 'format': 'image' }) component.setMeta(key='ftr_meta', value=metaData) version.setMeta(meta) version.createComponent(name='movie', path=filename) version.publish() except: job.setDescription('Failed to Upload Media') job.setStatus('failed') return version.setStatus(status) try: attachment = version.createThumbnail(filename) task = ftrack.Task(taskid) task.setThumbnail(attachment) except: job.setDescription('Failed to Upload Thumbnail') job.setStatus('failed') return job.setDescription('Upload complete for shot {0}'.format(shot.getName())) job.setStatus('done')
def update_context(self, context): '''Update based on *context*.''' logging.info('Building context from: {0}'.format( pprint.pformat(context))) if context['version']: contributors = session.query( 'select user_id from AssetVersion where id ' 'in ({0})'.format(','.join(context['version']))).all() for contributor in contributors: self._lookup[contributor['user_id']] = 'contributors' if context['task']: other_assignees = session.query( 'select id from User where assignments.context_id ' 'in ({0})'.format(','.join(context['task']))).all() for assignee in other_assignees: self._lookup[assignee['id']] = 'assigned' for task_id in context['task']: try: managers = ftrack.Task(task_id).getManagers() for manager in managers: self._lookup[manager.get('userid')] = 'supervisors' except Exception: logging.warning( 'Failed to get managers for task with id "{0}"'.format( task_id)) logging.info('_lookup contains "{0}"'.format(str(self._lookup)))
def launch(self, event): '''Callback method for custom action.''' selection = event['data'].get('selection', []) ####################################################################### job = ftrack.createJob(description="Creating Folders", status="running") try: ftrack.EVENT_HUB.publishReply(event, data={ 'success': True, 'message': 'Folder Creation Job Started!' }) for entity in selection: if entity['entityType'] == 'task': entity = ftrack.Task(entity['entityId']) else: entity = ftrack.Project(entity['entityId']) self.createFoldersFromEntity(entity) # inform the user that the job is done job.setStatus('done') except: job.setStatus('failed') raise ####################################################################### return {'success': True, 'message': 'Created Folders Successfully!'}
def process(self, instance): node = instance.data['model'] versionDir = instance.data['vprefix'] + instance.data['version'] publishDir = os.path.join(instance.data['publishDir'], versionDir) if not os.path.exists(publishDir): os.makedirs(publishDir) metadata = instance.data['metadata'] metadata['version'] = versionDir task = ftrack.Task(instance.context.data['taskid']) assetName = task.getParent().getName().lower() assetFile = os.path.join(publishDir, '%s_ref.mb' % assetName) refFile = os.path.join(instance.data['publishDir'], '%s_ref.mb' % assetName) metadata['publish_model'] = refFile pymel.core.select(node) pymel.core.system.exportSelected(assetFile, constructionHistory=False, preserveReferences=True, shader=True, constraints=False, force=True) if os.path.exists(refFile): os.remove(refFile) os.symlink(assetFile, refFile) self.log.info('Extraction completed successfully')
def main(port=9080): # setting Pyblish Window title task = ftrack.Task(os.environ['FTRACK_TASKID']) path = [task.getName()] for p in task.getParents(): path.append(p.getName()) path = ' / '.join(list(reversed(path))) pyblish_qml.settings.WindowTitle = path app_path = pyblish_qml.app.APP_PATH app = pyblish_qml.app.Application(app_path) app.__debugging__ = True app.listen() proxy = pyblish_rpc.client.Proxy(port) if not proxy.ping(): os.environ["PYBLISH_CLIENT_PORT"] = str(port) pyblish_rpc.server.start_async_production_server(port) print("Running standalone RPC server @ 127.0.0.1:%s" % port) app.show_signal.emit(port, {}) print("Running Pyblish QML standalone @ 127.0.0.1:9090") return app.exec_()
def process(self, instance): node = instance.data['rig'] versionDir = instance.data['vprefix'] + instance.data['version'] publishDir = os.path.join(instance.data['publishDir'], versionDir) if not os.path.exists(publishDir): os.makedirs(publishDir) metadata = instance.data['metadata'] metadata['version'] = versionDir task = ftrack.Task(instance.context.data['taskid']) assetName = task.getParent().getName().lower() assetFile = os.path.join(publishDir, '%s_rig.mb' % assetName) refFile = os.path.join(instance.data['publishDir'], '%s_rig.mb' % assetName) metadata['publish_rig'] = refFile with maintained_selection(): cmds.select(node, noExpand=True) cmds.file(assetFile, force=True, typ='mayaBinary', exportSelected=True, preserveReferences=False, constructionHistory=True) if os.path.exists(refFile): os.remove(refFile) os.symlink(assetFile, refFile) self.log.info('Extraction completed successfully')
def is_valid_selection(self, event): selection = event["data"].get("selection", []) if not selection: return entityType = selection[0]["entityType"] if entityType not in ["assetversion", "task"]: return False if entityType == "assetversion": version = ftrack.AssetVersion(selection[0]["entityId"]) # filter to image sequences and movies only if version.getAsset().getType().getShort() != "mov": return False if entityType == "task": task = ftrack.Task(selection[0]["entityId"]) # filter to tasks if task.getObjectType() != "Task": return False return True
def _onEntityBrowseButtonClicked(self): '''Handle entity browse button clicked.''' # Ensure browser points to parent of currently selected entity. if self._entity is not None: location = [] try: parents = self._entity.getParents() except AttributeError: pass else: for parent in parents: location.append(parent.getId()) location.reverse() self.entityBrowser.setLocation(location) # Launch browser. if self.entityBrowser.exec_(): selected = self.entityBrowser.selected() if selected: # Translate new api entity to instance of ftrack.Task # TODO: this should not be necessary once connect has been # updated to use the new api. if selected[0].entity_type == 'Project': entity = ftrack.Project(selected[0]['id']) else: entity = ftrack.Task(selected[0]['id']) self.setEntity(entity) else: self.setEntity(None)
def launch(self, event): if 'values' in event['data']: # Do something with the values or return a new form. values = event['data']['values'] success = True msg = 'Asset deleted.' asset = ftrack.Asset(values['asset']) asset.delete() return { 'success': success, 'message': msg } data = [] shot = ftrack.Task(event['data']['selection'][0]['entityId']) for asset in shot.getAssets(): if asset.getName(): data.append({'label': asset.getName(), 'value': asset.getId()}) else: data.append({'label': 'None', 'value': asset.getId()}) return { 'items': [ { 'label': 'Asset', 'type': 'enumerator', 'name': 'asset', 'data': data } ] }
def process(self, instance): import ftrack if not instance.context.has_data("ftrackData"): return job_data = {} plugin_data = {} if "deadlineData" in instance.data: job_data = instance.data["deadlineData"]["job"].copy() plugin_data = instance.data["deadlineData"]["plugin"].copy() # commenting to store full ftrack path comment = "" task = ftrack.Task(instance.context.data["ftrackData"]["Task"]["id"]) for p in reversed(task.getParents()): comment += p.getName() + "/" comment += task.getName() comment = "Ftrack path: \"{0}\"".format(comment) job_data["Comment"] = comment # setting data data = {"job": job_data, "plugin": plugin_data} instance.data["deadlineData"] = data
def updateEntity(self): try: entity = ftrack.Task(self.entityField.text()) except ftrack.FTrackError: entity = None self.setEntity(entity)
def get_thumbnail_recursive(task): if task.get('thumbid'): thumbid = task.get('thumbid') return ftrack.Attachment(id=thumbid) if not task.get('thumbid'): parent = ftrack.Task(id=task.get('parent_id')) return get_thumbnail_recursive(parent)
def callback(event): """ Status Handler. Sets status of task to the updated status of the asset version. If status of task or asset version is updated to "Ready for Lighting" or "Ready for Comp", sends a message to the assigned user. """ for entity in event['data'].get('entities', []): entityType = entity.get('entityType') if entityType == 'assetversion' and entity['action'] == 'update': if 'keys' not in entity or 'statusid' not in entity.get('keys'): return version = ftrack.AssetVersion(id=entity['entityId']) status = version.getStatus() # Set the task status to that of the asset version. task = version.getTask() task.setStatus(status) if status.getName() == 'Ready for Lighting': findTask(task, 'Lighting') elif status.getName() == 'Ready for Comp': findTask(task, 'Compositing') elif entityType == 'task' and entity['action'] == 'update': if 'keys' not in entity or 'statusid' not in entity.get('keys'): return task = ftrack.Task(id=entity['entityId']) status = task.getStatus() if status.getName() == 'Ready for Lighting': findTask(task, 'Lighting') elif status.getName() == 'Ready for Comp': findTask(task, 'Compositing')
def prePublish(cls, iAObj): '''Make certain scene validations before actualy publishing *iAObj*.''' parent = ftrack.Task(iAObj.taskId).getParent() if parent.get('entityType') == 'show': return None, 'Task parent cant be show' else: return True, ''
def getVersionsInSelection(self, selection): '''Return list of versions in *selection*.''' versions = [] for item in selection: self.logger.info( 'Looking for versions on entity ({0}, {1})'.format( item['entityId'], item['entityType'])) if item['entityType'] == 'assetversion': versions.append(ftrack.AssetVersion(item['entityId'])) continue entity = None if item['entityType'] == 'show': entity = ftrack.Project(item['entityId']) elif item['entityType'] == 'task': entity = ftrack.Task(item['entityId']) if not entity: continue assets = entity.getAssets(includeChildren=True) self.logger.info('Found {0} assets on entity'.format(len(assets))) for asset in assets: assetVersions = asset.getVersions() self.logger.info('Found {0} versions on asset {1}'.format( len(assetVersions), asset.getId())) versions.extend(assetVersions) self.logger.info('Found {0} versions in selection'.format( len(versions))) return versions
def _findLatestComponent(self, entityId, entityType, extension=''): '''Return latest published component from *entityId* and *entityType*. *extension* can be used to find suitable components by matching with their file system path. ''' if entityType == 'task': task = ftrack.Task(entityId) versions = task.getAssetVersions() elif entityType == 'assetversion': versions = [ftrack.AssetVersion(entityId)] else: self.logger.debug( ('Unable to find latest version from entityId={entityId} ' 'with entityType={entityType}.').format( entityId=entityId, entityType=entityType)) return None lastDate = None latestComponent = None for version in versions: for component in version.getComponents(): fileSystemPath = component.getFilesystemPath() if fileSystemPath and fileSystemPath.endswith(extension): if (lastDate is None or version.getDate() > lastDate): latestComponent = component lastDate = version.getDate() return latestComponent
def publishAsset(self): '''Publish the asset''' task = self.exportAssetOptionsWidget.getTask() taskId = task.getId() shot = self.exportAssetOptionsWidget.getShot() assettype = self.exportAssetOptionsWidget.getAssetType() assetName = self.exportAssetOptionsWidget.getAssetName() status = self.exportAssetOptionsWidget.getStatus() comment = self.exportOptionsWidget.getComment() options = self.exportOptionsWidget.getOptions() thumbnail = self.exportOptionsWidget.getThumbnail() if assetName == '': self.showWarning('Missing assetName', 'assetName can not be blank') return prePubObj = ftrack_connector.FTAssetObject(options=options, taskId=taskId) result, message = self.connector.prePublish(prePubObj, assettype) if not result: self.showWarning('Prepublish failed', message) return self.exportOptionsWidget.setProgress(0) asset = shot.createAsset(assetName, assettype) assetVersion = asset.createVersion(comment=comment, taskid=taskId) pubObj = ftrack_connector.FTAssetObject( assetVersionId=assetVersion.getId(), options=options) try: publishedComponents, message = self.connector.publishAsset(pubObj) except: self.exportOptionsWidget.setProgress(100) self.showError('Publish failed. Please check the console.') raise if publishedComponents: self.connector.publishAssetFiles(publishedComponents, assetVersion, pubObj) else: self.exportOptionsWidget.setProgress(100) # Update status of task. ftTask = ftrack.Task(id=taskId) if (ftTask and ftTask.get('object_typeid') == '11c137c0-ee7e-4f9c-91c5-8c77cec22b2c'): for taskStatus in ftrack.getTaskStatuses(): if (taskStatus.getName() == status and taskStatus.get('statusid') != ftTask.get('statusid')): try: ftTask.setStatus(taskStatus) except Exception, error: print 'warning: {0}'.format(error) break
def callback(event): """ This plugin sets the task status from the version status update. """ for entity in event['data'].get('entities', []): # Filter non-assetversions if entity.get('entityType') == 'task' and entity['action'] == 'update': # Find task if it exists task = None try: task = ftrack.Task(id=entity.get('entityId')) except: return # Filter to tasks with complete status check = False if task and task.get('objecttypename') == 'Task': if task.getStatus().get('name').lower() == 'supervisor review': check = True if check: # setting image sequence version_number = 0 version_latest = None for version in task.getAssetVersions(): if version.getAsset().getType().getShort() == 'img' and \ version.getVersion() > version_number: version_number = version.getVersion() version_latest = version if version_latest: status = utils.GetStatusByName('supervisor review') version_latest.setStatus(status) path = task.getParent().getName() + '/' path += version_latest.getAsset().getName() + ' ' path += 'v%s' % str(version_latest.getVersion()).zfill(2) print 'Setting %s "img" to "Supervisor Review"' % path # setting movie version_number = 0 version_latest = None for version in task.getAssetVersions(): if version.getAsset().getType().getShort() == 'mov' and \ version.getVersion() > version_number: version_number = version.getVersion() version_latest = version if version_latest: status = utils.GetStatusByName('supervisor review') version_latest.setStatus(status) path = task.getParent().getName() + '/' path += version_latest.getAsset().getName() + ' ' path += 'v%s' % str(version_latest.getVersion()).zfill(2) print 'Setting %s "mov" to "Supervisor Review"' % path
def _getApplicationEnvironment( self, application, context=None ): '''Override to modify environment before launch.''' # Make sure to call super to retrieve original environment # which contains the selection and ftrack API. environment = super( ApplicationLauncher, self )._getApplicationEnvironment(application, context) entity = context['selection'][0] task = ftrack.Task(entity['entityId']) taskParent = task.getParent() try: environment['FS'] = str(int(taskParent.getFrameStart())) except Exception: environment['FS'] = '1' try: environment['FE'] = str(int(taskParent.getFrameEnd())) except Exception: environment['FE'] = '1' environment['FTRACK_TASKID'] = task.getId() environment['FTRACK_SHOTID'] = task.get('parent_id') maya_connect_scripts = os.path.join(self.plugin_path, 'scripts') maya_connect_plugins = os.path.join(self.plugin_path, 'plug_ins') environment = ftrack_connect.application.appendPath( maya_connect_scripts, 'PYTHONPATH', environment ) environment = ftrack_connect.application.appendPath( maya_connect_scripts, 'MAYA_SCRIPT_PATH', environment ) environment = ftrack_connect.application.appendPath( maya_connect_plugins, 'MAYA_PLUG_IN_PATH', environment ) environment = ftrack_connect.application.appendPath( sources, 'PYTHONPATH', environment ) if application['version'] < LooseVersion('2017'): environment['QT_PREFERRED_BINDING'] = 'PySide' else: environment['QT_PREFERRED_BINDING'] = 'PySide2' return environment
def launch(self, event): """ Called when action is executed """ selection = event['data'].get('selection', []) task = ftrack.Task(selection[0]['entityId']) user = ftrack.User(id=event['source']['user']['id']) taskType = task.getType().getName().lower() taskFolder = self.getTaskFolder(task) if not os.path.exists(taskFolder): os.makedirs(taskFolder) shotName = task.getParent().getName() publishFile = '' newFilePath = os.path.join(taskFolder, '%s_v01.mb' % shotName) if taskType == 'previz': publishFile = self.copyFromLayoutPublish(taskFolder, 'previz') if os.path.exists(publishFile) and not os.path.exists(newFilePath): shutil.copy(publishFile, newFilePath) os.chmod(newFilePath, 0666) elif taskType == 'animation': previzDir = os.path.join( taskFolder.split('animation')[0], 'previz') previzFiles = [ f for f in glob.glob(os.path.join(previzDir, '*_v[0-9]*.mb')) ] # get latest previz file if previzFiles: maxVersion = 1 for f in previzFiles: try: version = int(self.version_get(f, 'v')[1]) except ValueError: continue if version >= maxVersion: publishFile = f maxVersion = version publishFile = os.path.join(previzDir, publishFile) # Else get latest layout publish file else: publishFile = self.copyFromLayoutPublish( taskFolder, 'animation') # Copy over the latest publish file. if os.path.exists(publishFile) and not os.path.exists(newFilePath): shutil.copy(publishFile, newFilePath) os.chmod(newFilePath, 0666) elif taskType == 'lighting': mayapy = '/usr/autodesk/maya2016/bin/mayapy' if os.path.exists(mayapy): self.buildLightingScene(mayapy, task.getId(), taskFolder, user, newFilePath, shotName) metadata = task.getMeta() metadata['filename'] = newFilePath task.setMeta(metadata) return {'success': True, 'message': 'Action launched successfully.'}
def setPyblishWindowTitle(): task = ftrack.Task(os.environ['FTRACK_TASKID']) path = [task.getName()] for p in task.getParents(): path.append(p.getName()) path = ' / '.join(list(reversed(path))) pyblish_qml.settings.WindowTitle = path
def setThumbnailFilename(self): '''Handle the thumbnail name generation''' shot = ftrack.Task(os.environ['FTRACK_SHOTID']) proj_root = shot.getProject().getRoot() fileName = QtWidgets.QFileDialog.getOpenFileName( self, self.tr("Open Image"), proj_root, self.tr("Image Files (*.png *.jpg *.jpeg")) self.ui.thumbnailLineEdit.setText(fileName[0])
def modify_application_launch(event): """Modify the application launch command with potential files to open""" selection = event["data"]["context"]["selection"] if not selection: return environment = {} app_id = event["data"]["application"]["label"].lower() # Nukex = Nuke, no special plugins for NukeX if app_id == "nukex": app_id = "nuke" # Get task type task_type = "" try: task_id = event["data"]["context"]["selection"][0]["entityId"] task = ftrack.Task(task_id) task_type = task.getType().getName().lower() except: pass # PYBLISHPLUGINPATH bumpybox_plugins_dir = os.path.join(os.environ["CONDA_GIT_REPOSITORY"], "pyblish-bumpybox", "pyblish_bumpybox", "plugins") environment_plugins_dir = os.path.join(os.environ["CONDA_GIT_REPOSITORY"], "blacksmithvfx-environment", "environment", "PYBLISHPLUGINPATH") environment["PYBLISHPLUGINPATH"] = [ os.path.join(environment_plugins_dir, "deadline"), os.path.join(environment_plugins_dir, "ftrack"), os.path.join(environment_plugins_dir, "houdini"), os.path.join(environment_plugins_dir, "maya"), os.path.join(environment_plugins_dir, "nuke"), bumpybox_plugins_dir, os.path.join(bumpybox_plugins_dir, app_id.split("_")[0]), os.path.join(bumpybox_plugins_dir, app_id.split("_")[0], task_type), os.path.join(bumpybox_plugins_dir, "ftrack"), os.path.join(bumpybox_plugins_dir, "deadline"), os.path.join(os.environ["CONDA_GIT_REPOSITORY"], "pyblish-ftrack", "pyblish_ftrack", "plugins"), os.path.join(os.environ["CONDA_GIT_REPOSITORY"], "pyblish-deadline", "pyblish_deadline", "plugins"), ] # adding variables data = event["data"] for variable in environment: for path in environment[variable]: appendPath(path, variable, data["options"]["env"]) return data
def callback(event): for entity in event['data'].get('entities', []): # Filter non-assetversions if entity.get('entityType') == 'task' and entity['action'] == 'update': if 'statusid' not in entity.get('keys'): return # Find task if it exists try: task = ftrack.Task(id=entity.get('entityId')) except: return # remove status assigned users if task.getMeta('assignees'): for userid in task.getMeta('assignees').split(','): try: task.unAssignUser(ftrack.User(userid)) except: pass # getting status named group task_status_name = task.getStatus().get('name').lower() project = task.getParents()[-1] status_group = None for group in project.getAllocatedGroups(): if group.getSubgroups(): if group.get('name').lower() == task_status_name: status_group = group users = [] if status_group: for group in status_group.getSubgroups(): task_type_name = task.getType().get('name').lower() if task_type_name == group.get('name').lower(): # assigning new users for member in group.getMembers(): try: task.assignUser(member) users.append(member.get('userid')) except: pass # storing new assignees value = '' for user in users: value += user + ',' try: value = value[:-1] except: pass task.setMeta('assignees', value=value)
def generateStructure(self, values, entityId): """Return structure from *values*.""" structure = [] if 'sequence_name' in values: seqName = values['sequence_name'] structure.append({'object_type': 'sequence', 'data': [seqName]}) else: seqName = ftrack.Task(entityId).getName() if 'shot_expression' in values: object_expression = values['shot_expression'] object_incremental = values['shot_incremental'] padding = object_expression.count('#') _range, incremental = object_incremental.split(':') start, end = _range.split('-') start = int(start) end = int(end) incremental = int(incremental) base_name = object_expression.replace('#', '') if values['addSeqPrefix'] == 'Yes': base_name = '%s_%s' % (seqName, base_name) logging.info( ('Create from expression {expression} with {base_name}, ' '{padding} and {start}-{end}:{incremental}').format( expression=object_expression, base_name=base_name, padding=padding, start=start, end=end, incremental=incremental)) names = self.getNames(base_name=base_name, padding=padding, start=start, end=end, incremental=incremental) structure.append({'object_type': 'shot', 'data': names}) tasks = collections.defaultdict(dict) for name, value in values.iteritems(): if name.startswith('task_'): _, index, key = name.split('_') if key == 'bid': value = float(value) * 3600 tasks[index][key] = value task_data = [] structure.append({'object_type': 'task', 'data': task_data}) for task in tasks.values(): task_data.append(task) return structure