Beispiel #1
0
    def pickLocation(copyFiles=False):
        '''Return a location based on *copyFiles*.'''
        location = None
        session = connect_session.get_shared_session()
        locations = session.query('select id, name from Location').all()

        sorted_locations = sorted(locations,
                                  key=lambda _location: _location.priority)

        visible_locations = filter(
            lambda _location: _location['name'] not in ('ftrack.origin', ),
            sorted_locations)

        for candidateLocation in visible_locations:
            if candidateLocation.accessor is not symbol.NOT_SET:
                # Can't copy files to an unmanaged location.
                if (copyFiles and isinstance(
                        candidateLocation,
                        ftrack_api.entity.location.UnmanagedLocationMixin)):
                    continue

                location = candidateLocation
                break

        return location
def action_launch(event):

    if "values" not in event["data"]:
        return

    session = get_shared_session()
    status = session.query("Status where name is \"Internal Review\"").one()
    for key, value in event["data"]["values"].iteritems():
        if value:
            session.get("AssetVersion", key)["status"] = status

    session.commit()
def modify_launch(event):
    """Return each entities in the selection in data dictionaries."""

    data = event["data"]
    task = get_shared_session().get(
        "Task", event["data"]["context"]["selection"][0]["entityId"])
    templates = lucidity.discover_templates()
    template_name = templates[0].get_template_name(task["parent"])
    for template in templates:
        if template.name == template_name:
            # Return first valid path. This is up to the templates
            # definition to order what comes first.
            return data["command"].extend(
                ["--path", template.format(task["parent"])])
Beispiel #4
0
    def __init__(self,
                 componentId='',
                 filePath='',
                 componentName='',
                 assetVersionId='',
                 options={},
                 taskId=''):
        '''Instantiate asset object.'''
        super(FTAssetObject, self).__init__()
        self.componentId = componentId
        self.filePath = filePath
        self.componentName = componentName
        self.shared_session = connect_session.get_shared_session()
        self.options = options
        self.setTotalSteps = True
        self.taskId = taskId

        if assetVersionId != '':
            assetVersion = self.shared_session.query(
                'select id, asset, asset.name,'
                ' asset.id, asset.type.short '
                ' from AssetVersion where id is "{0}"'.format(
                    assetVersionId)).one()
            self.assetVersionId = assetVersionId
            assetVersionStr = str(assetVersion['version'])
            self.assetVersion = assetVersionStr
            self.assetName = assetVersion['asset']['name']
            self.assetType = assetVersion['asset']['type']['short']
            self.assetId = assetVersion['asset']['id']

        if self.componentId != '':
            component = self.shared_session.query(
                'select name, version.asset.type.short, version.asset.name, '
                'version.asset.type.name, version.asset.versions.version, '
                'version.id, version.version, version.asset.versions, '
                'version.date, version.comment, version.asset.name, version, '
                'version_id, version.user.first_name, version.user.last_name '
                ' from Component where id is {0}'.format(
                    self.componentId)).one()
            self.metadata = []
            for k, v in component['metadata'].items():
                self.metadata.append((k, v))

        try:
            self.zversion = assetVersionStr.zfill(3)
        except:
            self.zversion = '000'
def application_launch(event):
    """Return each entities in the selection in data dictionaries."""

    session = get_shared_session()
    entity = session.get("Task",
                         event["data"]["context"]["selection"][0]["entityId"])
    entities = []
    for link in entity["link"]:
        entities.append(session.get(link["type"], link["id"]))

    event = inject_paths(event, entities)

    for path in event["data"]["directories"]:
        os.makedirs(path)

    for src, dst in event["data"]["files"]:
        print "Copying \"{0}\" to \"{1}\"".format(src, dst)

        if not os.path.exists(os.path.dirname(dst)):
            os.makedirs(os.path.dirname(dst))

        shutil.copy(src, dst)
    def process_review(self, src_asset_version, preset, tempdir):

        session = get_shared_session()

        src_component = session.query(
            "Component where version.id is \"{0}\" and "
            "name is \"ftrackreview-mp4\"".format(
                src_asset_version["id"])).first()

        # Get ftrack.server location
        server_location = session.query(
            "Location where name is \"ftrack.server\"").one()

        movie_path = self.download_component(src_component, tempdir,
                                             server_location)

        [review_path, thumbnail_path] = self.process_preset(movie_path, preset)

        self.create_review_components(review_path,
                                      src_asset_version,
                                      server_location,
                                      src_component,
                                      thumbnail_path=thumbnail_path)
    def process_review(self, src_asset_version, preset, tempdir):

        session = get_shared_session()

        src_component = session.query(
            "Component where version.id is \"{0}\" and "
            "name is \"ftrackreview-mp4\"".format(src_asset_version["id"])
        ).first()

        # Get ftrack.server location
        server_location = session.query(
            "Location where name is \"ftrack.server\""
        ).one()

        movie_path = self.download_component(
            src_component, tempdir, server_location
        )

        [review_path, thumbnail_path] = self.process_preset(movie_path, preset)

        self.create_review_components(
            review_path, src_asset_version, server_location,
            src_component, thumbnail_path=thumbnail_path
        )
def modify_launch(event):
    """Return each entities in the selection in data dictionaries."""

    session = get_shared_session()
    templates = lucidity.discover_templates()

    file_paths = []
    paths_searched = []
    for item in event["data"].get("selection", []):
        entity = session.get(item["entityType"].title(), item["entityId"])
        template_name = templates[0].get_template_name(entity["parent"])
        for template in templates:
            if template.name == template_name:
                path = template.format(entity["parent"])
                for root, subFolder, files in os.walk(path):
                    path = os.path.abspath(root)
                    if path in paths_searched:
                        continue
                    else:
                        paths_searched.append(path)
                    for f in files:
                        if not f.endswith(".exr"):
                            continue
                        file_paths.append(
                            os.path.abspath(os.path.join(root, f)))

    collections = clique.assemble(list(set(file_paths)))[0]
    for collection in collections:
        event["data"]["items"].append({
            "label":
            os.path.basename(collection.format()),
            "value":
            list(collection)[0]
        })

    return event
def callback(event):
    """Status change updates."""

    session = get_shared_session()

    for entity_data in event["data"].get("entities", []):

        if entity_data["action"] != "update":
            continue

        if "keys" not in entity_data:
            continue

        if "statusid" not in entity_data["keys"]:
            continue

        new_status = session.get(
            "Status", entity_data["changes"]["statusid"]["new"]
        )

        # AssetVersion changes
        if entity_data["entityType"] == "assetversion":
            entity = session.get("AssetVersion", entity_data["entityId"])

            if new_status["name"] == "Pending Changes":
                entity["task"]["status"] = new_status

            if new_status["name"] == "Internal Approval":
                entity["task"]["status"] = new_status

            if new_status["name"] == "External Review":
                entity["task"]["status"] = new_status

            if new_status["name"] == "External Approval":
                entity["task"]["status"] = new_status

        # Task changes
        if entity_data["entityType"] == "task":

            if new_status["name"] == "Internal Review":
                items = []

                # Description
                items.append(
                    {
                        "value": "## Please select which version(s) you want "
                        "to send for \"Internal Review\".",
                        "type": "label"
                    }
                )
                items.append(
                    {
                        "value": "## The current selection are version(s) that"
                        " are in \"In Progress\".",
                        "type": "label"
                    }
                )

                assetversions = session.query(
                    "select asset.name, version, id from AssetVersion where "
                    "task.id is \"{0}\" and status.name is "
                    "\"In Progress\"".format(entity_data["entityId"])
                )
                for assetversion in assetversions:
                    items.append(
                        {
                            "value": "{0} - v{1:02d}".format(
                                assetversion["asset"]["name"],
                                assetversion["version"]
                            ),
                            "type": "label"
                        }
                    )
                    items.append(
                        {
                            "label": "",
                            "name": assetversion["id"],
                            "value": False,
                            "type": "boolean"
                        }
                    )

                assetversions = session.query(
                    "select asset.name, version, id from AssetVersion where "
                    "task.id is \"{0}\" and status.name is_not "
                    "\"In Progress\"".format(entity_data["entityId"])
                )
                for assetversion in assetversions:
                    items.append(
                        {
                            "value": "{0} - v{1:02d}".format(
                                assetversion["asset"]["name"],
                                assetversion["version"]
                            ),
                            "type": "label"
                        }
                    )
                    items.append(
                        {
                            "label": "",
                            "name": assetversion["id"],
                            "value": False,
                            "type": "boolean"
                        }
                    )

                event = ftrack_api.event.base.Event(
                    topic="ftrack.action.trigger-user-interface",
                    data={
                        "type": "form",
                        "items": items,
                        "title": "Internal Review"
                    },
                    target=(
                        "applicationId=ftrack.client.web and "
                        "user.id={0}".format(
                            event["source"]["user"]["id"]
                        )
                    )
                )
                session.event_hub.publish(event)

    session.commit()
Beispiel #10
0
 def session(self):
     '''Return ftrack session.'''
     return get_shared_session()
    def create_review_components(self,
                                 movie_path,
                                 src_asset_version,
                                 server_location,
                                 src_component,
                                 thumbnail_path=""):

        session = get_shared_session()

        # Create Asset
        asset_data = {
            "name": src_asset_version["asset"]["name"] + "_review",
            "type": src_asset_version["asset"]["type"],
            "parent": src_asset_version["asset"]["parent"],
        }

        asset_entity = session.query(
            "Asset where name is \"{0}\" and type.id is \"{1}\" and parent.id "
            "is \"{2}\"".format(asset_data["name"], asset_data["type"]["id"],
                                asset_data["parent"]["id"])).first()

        if not asset_entity:
            asset_entity = session.create("Asset", asset_data)

        # Create AssetVersion
        assetversion_data = {
            "version": src_asset_version["version"],
            "asset": asset_entity,
            "task": src_asset_version["task"]
        }

        dst_asset_version = session.query(
            "AssetVersion where version is \"{0}\" and asset.id is \"{1}\" "
            "and task.id is \"{2}\"".format(
                assetversion_data["version"], assetversion_data["asset"]["id"],
                assetversion_data["task"]["id"])).first()

        if not dst_asset_version:
            dst_asset_version = session.create("AssetVersion",
                                               assetversion_data)

        session.commit()

        # Recreate movie component
        component_data = {
            "name": "ftrackreview-mp4",
            "version": dst_asset_version
        }

        movie_component = session.query(
            "Component where name is \"{0}\" and version.id is \"{1}\"".format(
                component_data["name"],
                component_data["version"]["id"],
            )).first()

        if movie_component:
            session.delete(movie_component)

        movie_component = dst_asset_version.create_component(
            movie_path, data=component_data, location=server_location)

        # Add metadata
        movie_component["metadata"] = dict(src_component["metadata"])

        session.commit()

        # Recreate thumbnail component if the file exists
        if not os.path.exists(thumbnail_path):
            return

        component_data = {"name": "thumbnail", "version": dst_asset_version}

        thumbnail_component = session.query(
            "Component where name is \"{0}\" and version.id is \"{1}\"".format(
                component_data["name"],
                component_data["version"]["id"],
            )).first()

        if thumbnail_component:
            session.delete(thumbnail_component)

        thumbnail_component = dst_asset_version.create_component(
            thumbnail_path, data=component_data, location=server_location)

        dst_asset_version["thumbnail_id"] = thumbnail_component["id"]

        session.commit()
Beispiel #12
0
    def publishAssetFiles(publishedComponents,
                          assetVersion,
                          pubObj,
                          moveFiles=False,
                          copyFiles=True,
                          progressCallback=None,
                          startProgress=0,
                          endProgress=100):
        '''Publish asset files.'''
        session = connect_session.get_shared_session()
        if progressCallback:
            progressCallback(startProgress)

        asset_version = session.get('AssetVersion', assetVersion.getId())
        for componentNumber, ftComponent in enumerate(publishedComponents):
            path = HelpFunctions.safeString(ftComponent.path)

            if ftComponent.componentname != 'thumbnail':

                location = Connector.pickLocation(copyFiles=copyFiles)

                try:
                    component = asset_version.create_component(
                        path=path,
                        data={'name': ftComponent.componentname},
                        location=location)

                    session.commit()

                except Exception as error:
                    errorMessage = (
                        'A problem occurred while writing your files. It is '
                        'possible the disk settings in ftrack are incorrect. If '
                        'you are an administrator in ftrack you can check the '
                        'settings in the Settings->Disks section from the web '
                        'interface. If you are not an administrator then please '
                        'ask your administrator to check the settings for you '
                        'or drop us a line at [email protected].')
                    QtWidgets.QMessageBox.critical(
                        None, 'ftrack: Failed to publish.', errorMessage)
                    print traceback.format_exc()
                    print error

                    return

            else:
                thumb = assetVersion.createThumbnail(path)
                try:
                    currentTask = assetVersion.getTask()
                    currentTask.setThumbnail(thumb)
                except Exception:
                    print 'no task'

                try:
                    shot = assetVersion.getAsset().getParent()
                    shot.setThumbnail(thumb)
                except Exception:
                    print 'no shot for some reason'

            if len(ftComponent.metadata) > 0:
                for k, v in ftComponent.metadata:
                    component['metadata'][k] = v

            if progressCallback:
                progressStep = (endProgress -
                                startProgress) / len(publishedComponents)
                progressCallback(startProgress + progressStep *
                                 (componentNumber + 1))

        asset_version['is_published'] = True
        session.commit()
        Connector.postPublish(pubObj, publishedComponents)

        if progressCallback:
            progressCallback(endProgress)
Beispiel #13
0
def callback(event):

    session = get_shared_session()

    for entity_data in event["data"].get("entities", []):

        # Filter to tasks
        if entity_data.get('entityType') != 'task':
            continue

        # Filter to updates
        if entity_data['action'] != 'update':
            continue

        # Filter to status changes
        if 'statusid' not in entity_data.get('keys'):
            continue

        # Filter to "Pending Changes"
        new_status = session.get("Status",
                                 entity_data["changes"]["statusid"]["new"])

        if new_status["name"].lower() != "pending changes":
            continue

        task = session.get("Task", entity_data["entityId"])
        user = session.get("User", event["source"]["user"]["id"])
        job = session.create(
            "Job", {
                "user": user,
                "status": "running",
                "data": json.dumps({"description": "Version Up Scene."})
            })
        session.commit()

        try:
            versions = session.query(
                "select version,components,asset.name,asset.parent,"
                "asset.type.id,asset.parent.id,asset.type.id from AssetVersion"
                " where task.id is \"{0}\" and asset.type.short is "
                "\"scene\"".format(task["id"]))

            latest_version = {"version": 0}
            for version in versions:
                if latest_version["version"] < version["version"]:
                    latest_version = version

            # Skip if no scene version was found
            if latest_version["version"] == 0:
                job["status"] = "done"
                continue

            # Skip if an empty scene version exists
            if len(latest_version["components"]) == 0:
                job["status"] = "done"
                continue

            # Create Asset
            asset_data = {
                "name": latest_version["asset"]["name"],
                "type": latest_version["asset"]["type"],
                "parent": latest_version["asset"]["parent"],
            }

            asset_entity = session.query(
                "Asset where name is \"{0}\" and type.id is \"{1}\" and "
                "parent.id is \"{2}\"".format(
                    asset_data["name"], asset_data["type"]["id"],
                    asset_data["parent"]["id"])).first()

            if not asset_entity:
                asset_entity = session.create("Asset", asset_data)

            # Create AssetVersion
            assetversion_data = {
                "version": latest_version["version"] + 1,
                "asset": asset_entity,
                "task": task
            }

            dst_asset_version = session.query(
                "AssetVersion where version is \"{0}\" and asset.id is "
                "\"{1}\" and task.id is \"{2}\"".format(
                    assetversion_data["version"],
                    assetversion_data["asset"]["id"],
                    assetversion_data["task"]["id"])).first()

            if not dst_asset_version:
                dst_asset_version = session.create("AssetVersion",
                                                   assetversion_data)

            session.commit()
        except:
            job["status"] = "failed"
        else:
            job["status"] = "done"

        session.commit()
Beispiel #14
0
    def __init__(self, parent=None):
        '''Initiate a publish view.'''
        super(Publisher, self).__init__(parent)

        self.session = get_shared_session()
        self.logger = logging.getLogger(__name__ + '.' +
                                        self.__class__.__name__)

        self._entity = None

        layout = QtWidgets.QVBoxLayout()

        self.setLayout(layout)

        self.browser = _data_drop_zone.DataDropZone()
        layout.addWidget(self.browser)
        self.browser.dataSelected.connect(self._onDataSelected)

        # Create a components list widget.
        self.componentsList = _components_list.ComponentsList()
        self.componentsList.setObjectName('publisher-componentlist')
        self.componentsList.itemsChanged.connect(
            self._onComponentListItemsChanged)
        layout.addWidget(self.componentsList, stretch=1)
        self.componentsList.hide()

        # Create form layout to keep track of publish form items.
        formLayout = QtWidgets.QFormLayout()
        layout.addLayout(formLayout, stretch=0)

        # Add entity selector.
        self.entitySelector = EntitySelector()
        formLayout.addRow('Linked to', self.entitySelector)

        # Add asset options.
        self.assetOptions = _asset_options.AssetOptions()
        self.entitySelector.entityChanged.connect(self.assetOptions.setEntity)
        self.assetCreated.connect(self.assetOptions.setAsset)
        formLayout.addRow('Asset', self.assetOptions.radioButtonFrame)
        formLayout.addRow('Existing asset',
                          self.assetOptions.existingAssetSelector)
        formLayout.addRow('Type', self.assetOptions.assetTypeSelector)
        formLayout.addRow('Name', self.assetOptions.assetNameLineEdit)
        self.assetOptions.initializeFieldLabels(formLayout)

        # Add preview selector.
        self.previewSelector = _item_selector.ItemSelector(
            labelField='componentName',
            defaultLabel='Unnamed component',
            emptyLabel='Select component to use')
        formLayout.addRow('Web playable', self.previewSelector)

        self.thumbnailDropZone = _thumbnail_drop_zone.ThumbnailDropZone()
        formLayout.addRow('Thumbnail', self.thumbnailDropZone)

        # Add version description component.
        self.versionDescription = QtWidgets.QTextEdit()
        formLayout.addRow('Description', self.versionDescription)

        publishButton = QtWidgets.QPushButton(text='Publish')
        publishButton.setObjectName('primary')
        publishButton.clicked.connect(self.publish)

        layout.addWidget(publishButton,
                         alignment=QtCore.Qt.AlignCenter,
                         stretch=0)
Beispiel #15
0
 def __init__(self, session=None):
     '''Instantiate base connector.'''
     super(Connector, self).__init__()
     self.session = session or connect_session.get_shared_session()
    def create_review_components(self, movie_path,
                                 src_asset_version, server_location,
                                 src_component, thumbnail_path=""):

        session = get_shared_session()

        # Create Asset
        asset_data = {
            "name": src_asset_version["asset"]["name"] + "_review",
            "type": src_asset_version["asset"]["type"],
            "parent": src_asset_version["asset"]["parent"],
        }

        asset_entity = session.query(
            "Asset where name is \"{0}\" and type.id is \"{1}\" and parent.id "
            "is \"{2}\"".format(
                asset_data["name"],
                asset_data["type"]["id"],
                asset_data["parent"]["id"]
            )
        ).first()

        if not asset_entity:
            asset_entity = session.create("Asset", asset_data)

        # Create AssetVersion
        assetversion_data = {
            "version": src_asset_version["version"],
            "asset": asset_entity,
            "task": src_asset_version["task"]
        }

        dst_asset_version = session.query(
            "AssetVersion where version is \"{0}\" and asset.id is \"{1}\" "
            "and task.id is \"{2}\"".format(
                assetversion_data["version"],
                assetversion_data["asset"]["id"],
                assetversion_data["task"]["id"]
            )
        ).first()

        if not dst_asset_version:
            dst_asset_version = session.create(
                "AssetVersion", assetversion_data
            )

        session.commit()

        # Recreate movie component
        component_data = {
            "name": "ftrackreview-mp4",
            "version": dst_asset_version
        }

        movie_component = session.query(
            "Component where name is \"{0}\" and version.id is \"{1}\"".format(
                component_data["name"],
                component_data["version"]["id"],
            )
        ).first()

        if movie_component:
            session.delete(movie_component)

        movie_component = dst_asset_version.create_component(
            movie_path,
            data=component_data,
            location=server_location
        )

        # Add metadata
        movie_component["metadata"] = dict(src_component["metadata"])

        session.commit()

        # Recreate thumbnail component if the file exists
        if not os.path.exists(thumbnail_path):
            return

        component_data = {
            "name": "thumbnail",
            "version": dst_asset_version
        }

        thumbnail_component = session.query(
            "Component where name is \"{0}\" and version.id is \"{1}\"".format(
                component_data["name"],
                component_data["version"]["id"],
            )
        ).first()

        if thumbnail_component:
            session.delete(thumbnail_component)

        thumbnail_component = dst_asset_version.create_component(
            thumbnail_path,
            data=component_data,
            location=server_location
        )

        dst_asset_version["thumbnail_id"] = thumbnail_component["id"]

        session.commit()
Beispiel #17
0
    def launch(self, event):
        """Callback method for DJVView action."""

        # Launching application
        if "values" in event["data"]:

            applicationIdentifier = event["data"]["applicationIdentifier"]
            application = self.applicationStore.getApplication(
                applicationIdentifier
            )
            context = event["data"].copy()
            context["source"] = event["source"]
            command = self.launcher._getApplicationLaunchCommand(
                application, context
            )

            success = True
            message = '{0} application started.'.format(application['label'])

            command.append(event["data"]["values"]["path"])

            try:
                options = dict(
                    env={},
                    close_fds=True
                )

                # Ensure subprocess is detached so closing connect will not
                # also close launched applications.
                if sys.platform == 'win32':
                    options['creationflags'] = subprocess.CREATE_NEW_CONSOLE
                else:
                    options['preexec_fn'] = os.setsid

                self.logger.debug(
                    'Launching {0} with options {1}'.format(command, options)
                )
                process = subprocess.Popen(command, **options)

            except (OSError, TypeError):
                self.logger.exception(
                    '{0} application could not be started with command "{1}".'
                    .format(applicationIdentifier, command)
                )

                success = False
                message = '{0} application could not be started.'.format(
                    application['label']
                )

            else:
                self.logger.debug(
                    '{0} application started. (pid={1})'.format(
                        applicationIdentifier, process.pid
                    )
                )

            return {
                'success': success,
                'message': message
            }

        data = event["data"]
        data["items"] = []

        # Starting a job to show user the progress of scanning for files.
        job = ftrack.createJob("DJV: Scanning for files.", "queued",
                               ftrack.User(id=event["source"]["user"]["id"]))
        job.setStatus("running")

        try:
            ftrack.EVENT_HUB.publish(
                ftrack.Event(
                    topic='djvview.launch',
                    data=data
                ),
                synchronous=True
            )
            session = get_shared_session()
            session.event_hub.publish(
                ftrack_api.event.base.Event(
                    topic='djvview.launch',
                    data=data
                ),
                synchronous=True
            )
        except:
            job.setStatus("failed")
        else:
            job.setStatus("done")

        return {
            "items": [
                {
                    "label": "Items to view",
                    "type": "enumerator",
                    "name": "path",
                    "data": sorted(
                        data["items"],
                        key=itemgetter("label"),
                        reverse=True
                    )
                }
            ]
        }
Beispiel #18
0
# :coding: utf-8
# :copyright: Copyright (c) 2018 ftrack


import hiero.core

import lucidity
import lucidity.error

import ftrack_api

import ftrack_connect_nuke_studio.exception

from ftrack_connect.session import get_shared_session

session = get_shared_session()


def available_templates(project):
    '''Return available templates for *project*.

    If a template has been saved on the project using
    :meth:`save_project_template` that template will contain a `default` key
    set to True.

    '''
    templates = []
    responses = session.event_hub.publish(
        ftrack_api.event.base.Event(
            topic='ftrack.connect.nuke-studio.get-context-templates'
        ),