Example #1
0
    def test_update_paths_will_preserve_extension(self):
        """testing if update_paths method will preserve the extension.
        """
        # create a FilenameTemplate for Task instances
        ft = FilenameTemplate(
            name="Task Filename Template",
            target_entity_type="Task",
            path="{{project.code}}/{%- for parent_task in parent_tasks -%}" "{{parent_task.nice_name}}/{%- endfor -%}",
            filename="{{task.nice_name}}_{{version.take_name}}"
            '_v{{"%03d"|format(version.version_number)}}{{extension}}',
        )
        self.test_project.structure.templates.append(ft)
        new_version1 = Version(**self.kwargs)
        DBSession.add(new_version1)
        DBSession.commit()
        new_version1.update_paths()

        self.assertEqual(new_version1.path, "tp/SH001/Task1")

        extension = ".ma"
        new_version1.extension = extension
        self.assertEqual(new_version1.filename, "Task1_TestTake_v001.ma")

        # rename the task and update the paths
        self.test_task1.name = "Task2"

        # now call update_paths and expect the extension to be preserved
        new_version1.update_paths()
        self.assertEqual(new_version1.filename, "Task2_TestTake_v001.ma")
        self.assertEqual(new_version1.extension, extension)
Example #2
0
    def upload_version(self, task, file_object, take_name=None, extension=''):
        """Uploads versions to the Task.path/ folder and creates a Version
        object to there. Again the Version object will have a Repository root
        relative path.

        The filename of the version will be automatically generated by Stalker.

        :param task: The task that a version is uploaded to. Should be an
          instance of :class:`.Task` class.
        :param file_object: A file like object holding the content of the
          version.
        :param str take_name: A string showing the the take name of the
          Version. If skipped defaults.version_take_name will be used.
        :param str extension: The file extension of the version.
        :returns: :class:`.Version` instance.
        """
        from stalker import defaults, Version
        if take_name is None:
            take_name = defaults.version_take_name

        v = Version(task=task,
                    take_name=take_name,
                    created_with='Stalker Pyramid')
        v.update_paths()
        v.extension = extension

        # upload it
        self.upload_file(file_object, v.absolute_path, v.filename)

        return v
Example #3
0
    def test_absolute_full_path_works_properly(self):
        """testing if the absolute_full_path attribute works properly
        """
        ft = FilenameTemplate(
            name="Task Filename Template",
            target_entity_type="Task",
            path="{{project.code}}/{%- for parent_task in parent_tasks -%}" "{{parent_task.nice_name}}/{%- endfor -%}",
            filename="{{task.nice_name}}_{{version.take_name}}"
            '_v{{"%03d"|format(version.version_number)}}{{extension}}',
        )
        self.test_project.structure.templates.append(ft)
        new_version1 = Version(**self.kwargs)
        DBSession.add(new_version1)
        DBSession.commit()

        new_version1.update_paths()
        new_version1.extension = ".ma"
        self.assertEqual(new_version1.extension, ".ma")

        self.assertEqual(new_version1.absolute_full_path, "/mnt/T/tp/SH001/Task1/Task1_TestTake_v001.ma")
Example #4
0
def export_camera():
    """exports camera and the related shot node
    """
    from stalker import Task, Version
    from anima.env import mayaEnv

    m = mayaEnv.Maya()

    v = m.get_current_version()

    shot = pm.ls(type='shot')[0]
    try:
        sequencer = pm.ls(shot.message.connections(), type='sequencer')[0]
    except IndexError:
        sequencer = None

    camera = None
    if shot:
        camera = shot.currentCamera.get()

    camera_task = \
        Task.query\
            .filter(Task.parent == v.task.parent)\
            .filter(Task.name == 'Camera').first()

    if camera_task:
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        cam_v = Version(task=camera_task,
                        description='Exported from %s task on Publish' %
                        v.task.name)
        cam_v.update_paths()
        cam_v.extension = '.ma'
        cam_v.is_published = True
        cam_v.created_by = cam_v.updated_by = logged_in_user

        pm.select([shot, camera, sequencer])

        m.export_as(cam_v)
Example #5
0
    def copy_versions(self):
        """copies versions from one task to another
        """
        # get from task
        from_task = self.get_task_from_tree_view(self.from_task_tree_view)

        # get logged in user
        logged_in_user = self.get_logged_in_user()

        if not from_task:
            QtWidgets.QMessageBox.critical(
                self, 'Error',
                'Please select a task from <b>From Task</b> list')
            return

        # get to task
        to_task = self.get_task_from_tree_view(self.to_task_tree_view)

        if not to_task:
            QtWidgets.QMessageBox.critical(
                self, 'Error', 'Please select a task from <b>To Task</b> list')
            return

        # check if tasks are the same
        if from_task == to_task:
            QtWidgets.QMessageBox.critical(
                self, 'Error', 'Please select two different tasks')
            return

        # get take names and related versions
        # get distinct take names
        from stalker.db.session import DBSession
        from_take_names = map(
            lambda x: x[0],
            DBSession.query(distinct(Version.take_name)).filter(
                Version.task == from_task).order_by(Version.take_name).all())

        # create versions for each take
        answer = QtWidgets.QMessageBox.question(
            self, 'Info', "Will copy %s versions from take names:<br><br>"
            "%s"
            "<br><br>"
            "Is that Ok?" %
            (len(from_take_names), '<br>'.join(from_take_names)),
            QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)

        if answer == QtWidgets.QMessageBox.Yes:
            for take_name in from_take_names:
                latest_version = Version.query\
                    .filter_by(task=from_task)\
                    .filter_by(take_name=take_name)\
                    .order_by(Version.version_number.desc())\
                    .first()

                # create a new version
                new_version = Version(task=to_task, take_name=take_name)
                new_version.created_by = logged_in_user
                new_version.extension = latest_version.extension
                new_version.description = \
                    'Moved from another task (id=%s) with Version Mover' % \
                    latest_version.task.id
                new_version.created_with = latest_version.created_with
                DBSession.add(new_version)
                DBSession.commit()

                # update path
                new_version.update_paths()
                DBSession.add(new_version)
                DBSession.commit()

                # now copy the last_version file to the new_version path
                try:
                    os.makedirs(new_version.absolute_path)
                except OSError:  # path exists
                    pass

                # move the file there
                shutil.copyfile(latest_version.absolute_full_path,
                                new_version.absolute_full_path)

            # inform the user
            QtWidgets.QMessageBox.information(
                self, 'Success',
                'Successfully copied %s versions' % len(from_take_names))
Example #6
0
             repository=repo,
             structure=flat_struct)

# now lets create a Task
t1 = Task(name='Building 1', project=p1)
t2 = Task(name='Model', parent=t1)
t3 = Task(name='Lighting', parent=t1, depends=[t2])

# store all the data in the database
db.DBSession.add_all([t1, t2, t3])  # this is enough to store the rest

# lets create a Maya file for the Model task
t2_v1 = Version(task=t1)
t2_v1.update_paths()  # for now this is needed to render the template, but will
# remove it later on
t2_v1.extension = '.ma'  # set the extension for maya

# lets create a new version for Lighting
t3_v1 = Version(task=t3)
t3_v1.update_paths()
t3_v1.extension = '.ma'

# you should see that all are in the same folder
print(t2_v1.absolute_full_path)
print(t3_v1.absolute_full_path)

#
# Lets create a second Project that use some other folder structure
#

# create a new project structure
)

# now lets create a Task
t1 = Task(name='Building 1', project=p1)
t2 = Task(name='Model', parent=t1)
t3 = Task(name='Lighting', parent=t1, depends=[t2])

# store all the data in the database
db.DBSession.add_all([t1, t2, t3])  # this is enough to store the rest


# lets create a Maya file for the Model task
t2_v1 = Version(task=t1)
t2_v1.update_paths()  # for now this is needed to render the template, but will
                   # remove it later on
t2_v1.extension = '.ma'  # set the extension for maya

# lets create a new version for Lighting
t3_v1 = Version(task=t3)
t3_v1.update_paths()
t3_v1.extension = '.ma'

# you should see that all are in the same folder
print(t2_v1.absolute_full_path)
print(t3_v1.absolute_full_path)

#
# Lets create a second Project that use some other folder structure
#

# create a new project structure
Example #8
0
    def copy_versions(self):
        """copies versions from one task to another
        """
        # get from task
        from_task = self.get_task_from_tree_view(self.from_task_tree_view)

        # get logged in user
        logged_in_user = self.get_logged_in_user()

        if not from_task:
            QtWidgets.QMessageBox.critical(
                self,
                'Error',
                'Please select a task from <b>From Task</b> list'
            )
            return

        # get to task
        to_task = self.get_task_from_tree_view(self.to_task_tree_view)

        if not to_task:
            QtWidgets.QMessageBox.critical(
                self,
                'Error',
                'Please select a task from <b>To Task</b> list'
            )
            return

        # check if tasks are the same
        if from_task == to_task:
            QtWidgets.QMessageBox.critical(
                self,
                'Error',
                'Please select two different tasks'
            )
            return

        # get take names and related versions
        # get distinct take names
        from_take_names = map(
            lambda x: x[0],
            db.DBSession.query(distinct(Version.take_name))
            .filter(Version.task == from_task)
            .order_by(Version.take_name)
            .all()
        )

        # create versions for each take
        answer = QtWidgets.QMessageBox.question(
            self,
            'Info',
            "Will copy %s versions from take names:<br><br>"
            "%s"
            "<br><br>"
            "Is that Ok?" % (
                len(from_take_names),
                '<br>'.join(from_take_names)
            ),
            QtWidgets.QMessageBox.Yes,
            QtWidgets.QMessageBox.No
        )

        if answer == QtWidgets.QMessageBox.Yes:
            for take_name in from_take_names:
                latest_version = Version.query\
                    .filter_by(task=from_task)\
                    .filter_by(take_name=take_name)\
                    .order_by(Version.version_number.desc())\
                    .first()

                # create a new version
                new_version = Version(
                    task=to_task,
                    take_name=take_name
                )
                new_version.created_by = logged_in_user
                new_version.extension = latest_version.extension
                new_version.description = \
                    'Moved from another task (id=%s) with Version Mover' % \
                    latest_version.task.id
                new_version.created_with = latest_version.created_with
                db.DBSession.add(new_version)
                db.DBSession.commit()

                # update path
                new_version.update_paths()
                db.DBSession.add(new_version)
                db.DBSession.commit()

                # now copy the last_version file to the new_version path
                try:
                    os.makedirs(new_version.absolute_path)
                except OSError:  # path exists
                    pass

                # move the file there
                shutil.copyfile(
                    latest_version.absolute_full_path,
                    new_version.absolute_full_path
                )

            # inform the user
            QtWidgets.QMessageBox.information(
                self,
                'Success',
                'Successfully copied %s versions' % len(from_take_names)
            )
Example #9
0
def test_readme_tutorial_code(setup_sqlite3):
    """Tests the tutorial code in README.rst
    """
    from stalker import db
    db.setup()
    db.init()

    from stalker.db.session import DBSession
    assert str(DBSession.connection().engine.url) == 'sqlite://'

    from stalker import User
    me = User(name='Erkan Ozgur Yilmaz',
              login='******',
              email='*****@*****.**',
              password='******')

    # Save the user to database
    DBSession.save(me)

    from stalker import Repository
    repo = Repository(name='Commercial Projects Repository',
                      code='CPR',
                      windows_path='Z:/Projects',
                      linux_path='/mnt/Z/Projects',
                      osx_path='/Volumes/Z/Projects')

    from stalker import FilenameTemplate

    task_template = FilenameTemplate(
        name='Standard Task Filename Template',
        target_entity_type='Task',  # This is for files saved for Tasks
        path='{{project.repository.path}}/{{project.code}}/'
        '{%- for parent_task in parent_tasks -%}'
        '{{parent_task.nice_name}}/'
        '{%- endfor -%}',  # This is Jinja2 template code
        filename=
        '{{version.nice_name}}_v{{"%03d"|format(version.version_number)}}')

    from stalker import Structure
    standard_folder_structure = Structure(
        name='Standard Project Folder Structure',
        templates=[task_template],
        custom_template=
        '{{project.code}}/References'  # If you need extra folders
    )

    from stalker import Project
    new_project = Project(
        name='Test Project',
        code='TP',
        structure=standard_folder_structure,
        repositories=[repo
                      ],  # if you have more than one repository you can do it
    )

    from stalker import ImageFormat
    hd1080 = ImageFormat(name='1080p', width=1920, height=1080)

    new_project.image_format = hd1080

    # Save the project and all the other data it is connected to it
    DBSession.save(new_project)

    from stalker import Task, Asset, Shot, Type

    # define Character asset type
    char_type = Type(name='Character', code='CHAR', target_entity_type='Asset')

    character1 = Asset(name='Character 1',
                       code='CHAR1',
                       type=char_type,
                       project=new_project)

    # Save the Asset
    DBSession.save(character1)

    model = Task(name='Model', parent=character1)

    rigging = Task(
        name='Rig',
        parent=character1,
        depends=[model
                 ],  # For project management, define that Rig can not start
        # before Model ends.
    )

    # Save the new tasks
    DBSession.save([model, rigging])

    # A shot and some tasks for it
    shot = Shot(name='SH001', code='SH001', project=new_project)

    # Save the Shot
    DBSession.save(shot)

    animation = Task(
        name='Animation',
        parent=shot,
    )

    lighting = Task(
        name='Lighting',
        parent=shot,
        depends=[animation],  # Lighting can not start before Animation ends,
        schedule_timing=1,
        schedule_unit='d',  # The task expected to take 1 day to complete
        resources=[me])
    DBSession.save([animation, lighting])

    from stalker import Version

    new_version = Version(task=animation)
    new_version.update_paths()  # to render the naming convention template
    new_version.extension = '.ma'  # let's say that we have created under Maya

    assert new_version.absolute_full_path == \
        "%sTP/SH001/Animation/SH001_Animation_Main_v001.ma" % \
        repo.path
    assert new_version.version_number == 1

    new_version2 = Version(task=animation)
    new_version2.update_paths()  # to render the naming convention template
    new_version2.extension = '.ma'  # let's say that we have created under Maya

    assert new_version2.version_number == 2
Example #10
0
def assign_version(request):
    """assigns the version to the given entity
    """
    logged_in_user = get_logged_in_user(request)

    # TODO: this should be renamed to create version
    # collect data
    link_ids = get_multi_integer(request, 'link_ids')
    task_id = request.params.get('task_id', -1)

    link = Link.query.filter(Link.id.in_(link_ids)).first()
    task = Task.query.filter_by(id=task_id).first()

    logger.debug('link_ids  : %s' % link_ids)
    logger.debug('link      : %s' % link)
    logger.debug('task_id   : %s' % task_id)
    logger.debug('task      : %s' % task)

    if task and link:
        # delete the link and create a version instead
        full_path = convert_file_link_to_full_path(link.full_path)
        take_name = request.params.get('take_name', defaults.version_take_name)
        publish = bool(request.params.get('publish'))

        logger.debug('publish : %s' % publish)

        path_and_filename, extension = os.path.splitext(full_path)

        version = Version(task=task, take_name=take_name,
                          created_by=logged_in_user)
        version.is_published = publish

        # generate path values
        version.update_paths()
        version.extension = extension

        # specify that this version is created with Stalker Pyramid
        version.created_with = 'StalkerPyramid'  # TODO: that should also be a
                                                 #       config value

        # now move the link file to the version.absolute_full_path
        try:
            os.makedirs(
                os.path.dirname(version.absolute_full_path)
            )
        except OSError:
            # dir exists
            pass

        logger.debug('full_path : %s' % full_path)
        logger.debug('version.absolute_full_path : %s' %
                     version.absolute_full_path)

        shutil.copyfile(full_path, version.absolute_full_path)
        os.remove(full_path)

        # it is now safe to delete the link
        DBSession.add(task)
        DBSession.delete(link)
        DBSession.add(version)

    return HTTPOk()
Example #11
0
    def test_update_paths_will_render_the_appropriate_template_from_the_related_project(self):
        """testing if update_paths method will update the Version.full_path by
        rendering the related Project FilenameTemplate.
        """
        # create a FilenameTemplate for Task instances

        # A Template for Assets
        # ......../Assets/{{asset.type.name}}/{{asset.nice_name}}/{{task.type.name}}/
        #
        # Project1/Assets/Character/Sero/Modeling/Sero_Modeling_Main_v001.ma
        #
        # + Project1
        # |
        # +-+ Assets (Task)
        # | |
        # | +-+ Characters
        # |   |
        # |   +-+ Sero (Asset)
        # |     |
        # |     +-> Version 1
        # |     |
        # |     +-+ Modeling (Task)
        # |       |
        # |       +-+ Body Modeling (Task)
        # |         |
        # |         +-+ Coarse Modeling (Task)
        # |         | |
        # |         | +-> Version 1 (Version)
        # |         |
        # |         +-+ Fine Modeling (Task)
        # |           |
        # |           +-> Version 1 (Version): Fine_Modeling_Main_v001.ma
        # |                                  Assets/Sero/Modeling/Body_Modeling/Fine_Modeling/Fine_Modeling_Main_v001.ma
        # |
        # +-+ Shots (Task)
        #   |
        #   +-+ Shot 10 (Shot)
        #   | |
        #   | +-+ Layout (Task)
        #   |   |
        #   |   +-> Version 1 (Version): Layout_v001.ma
        #   |                            Shots/Shot_1/Layout/Layout_Main_v001.ma
        #   |
        #   +-+ Shot 2 (Shot)
        #     |
        #     +-+ FX (Task)
        #       |
        #       +-> Version 1 (Version)

        ft = FilenameTemplate(
            name="Task Filename Template",
            target_entity_type="Task",
            path="{{project.code}}/{%- for parent_task in parent_tasks -%}" "{{parent_task.nice_name}}/{%- endfor -%}",
            filename="{{task.nice_name}}_{{version.take_name}}"
            '_v{{"%03d"|format(version.version_number)}}{{extension}}',
        )
        self.test_project.structure.templates.append(ft)
        new_version1 = Version(**self.kwargs)
        DBSession.add(new_version1)
        DBSession.commit()
        new_version1.update_paths()

        self.assertEqual(new_version1.path, "tp/SH001/Task1")

        new_version1.extension = ".ma"
        self.assertEqual(new_version1.filename, "Task1_TestTake_v001.ma")
    def test_naming_case(self):
        """Test the case where naming should contain both Sequence Shot and
        other stuff
        (this is based on https://github.com/eoyilmaz/anima/issues/23)
        """
        from stalker.db.session import DBSession
        from stalker import Project, Task, Sequence, Shot, FilenameTemplate, \
            Version, Structure

        ft = FilenameTemplate(
            name='Normal Naming Convention',
            target_entity_type='Task',
            path=
            '$REPO{{project.repository.id}}/{{project.code}}/{%- for parent_task in parent_tasks -%}{{parent_task.nice_name}}/{%- endfor -%}',
            filename="""{%- for p in parent_tasks -%}
                {%- if p.entity_type == 'Sequence' -%}
                    {{p.name}}
                {%- elif p.entity_type == 'Shot' -%}
                    _{{p.name}}{{p.children[0].name}}
                {%- endif -%}
            {%- endfor -%}
            {%- set fx = parent_tasks[-2] -%}
            _{{fx.name}}_{{version.take_name}}_v{{"%02d"|format(version.version_number)}}""",
        )
        DBSession.add(ft)

        st = Structure(name='Normal Project Structure', templates=[ft])
        DBSession.add(st)

        test_project = Project(name='test001', code='test001', structure=st)
        DBSession.add(test_project)
        DBSession.commit()

        seq_task = Task(name='seq', project=test_project)
        DBSession.add(seq_task)

        ep101 = Sequence(name='ep101', code='ep101', parent=seq_task)
        DBSession.add(ep101)

        shot_task = Task(name='shot', parent=ep101)
        DBSession.add(shot_task)

        s001 = Shot(name='s001', code='s001', parent=shot_task)
        DBSession.add(s001)

        c001 = Task(name='c001', parent=s001)
        DBSession.add(c001)

        effects_scene = Task(name='effectScenes', parent=c001)
        DBSession.add(effects_scene)

        fxA = Task(name='fxA', parent=effects_scene)
        DBSession.add(fxA)

        maya = Task(name='maya', parent=fxA)
        DBSession.add(maya)
        DBSession.commit()

        v = Version(task=maya)
        v.update_paths()
        v.extension = '.ma'
        DBSession.add(v)
        DBSession.commit()

        assert v.filename == 'ep101_s001c001_fxA_Main_v01.ma'