Remus Avram

Members
  • Content Count

    490
  • Joined

  • Days Won

    13

Posts posted by Remus Avram


  1. Thanks @Mattias Lagergren for your answer!

    For us it's quite important because we are planing to use threads in all of our tools. We would like to use at least 1 thread in order to not freeze the UI while it is fetching the data.

    2 minutes ago, Mattias Lagergren said:

    One possible way to move forward with this is to change the example above and pass in the project id to the threads and then query for TypedContext where project_id is <project_id> in the thread.

    You mean something like this:

    from multiprocessing.dummy import Pool as ThreadPool
    
    import ftrack_api
    from ftrack_api.symbol import Symbol
    
    
    session = ftrack_api.Session()
    
    
    def check_keys(entity):
        for key in entity.keys():
            if isinstance(entity[key], Symbol):
                print entity, ': ', key
    
    
    def check_children(entity_id):
        entity = session.get('TypedContext', entity_id)
        if 'children' in entity.keys():
            for child in entity['children']:
                check_keys(entity=child)
                check_children(entity_id=child['id'])
    
    
    def main():
        projects = session.query("Project").all()
        projects_id = [project["id"] for project in projects]
        pool = ThreadPool()
        pool.map(check_children, projects_id)
    
    
    if __name__ == "__main__":
        main()

    It still doesn't work. In the thread most of the time session.get('TypedContext', entity_id) returns None.


  2. Hi Mattias,

    ahh... are you going to make it thread safe?

    The problem is that if it is not specified when the session is created to not auto-populate, then it should never return a Symbol (NOT SET) value.

    Creating a session per thread works as expected. But it doesn't help us as the sessions are not connected.


  3. Hi Ftrack Team,

    we would like to use the ftrack session in threads, but, unfortunately, it seems that ftrack_api is not thread safe.

    When we are using the session in multiple threads the return of the attribute value of the entities is a Symbol (NOT SET).

    Please find below a script where we were able to reproduce the issue:

    from multiprocessing.dummy import Pool as ThreadPool
    
    import ftrack_api
    from ftrack_api.symbol import Symbol
    
    
    session = ftrack_api.Session()
    
    
    def check_keys(entity):
        for key in entity.keys():
            if isinstance(entity[key], Symbol):
                print entity, ': ', key
    
    
    def check_children(entity):
        if 'children' in entity.keys():
            for child in entity['children']:
                check_keys(entity=child)
                check_children(entity=child)
    
    
    def main():
        projects = session.query("Project").all()
        pool = ThreadPool()
        pool.map(check_children, projects)
    
    
    if __name__ == "__main__":
        main()

    ftrack_api version: 1.3.2

    ftrack server version: 3.5.6

     


  4. Thanks @Mattias Lagergren for you answer.

    But is it possible to manually re-register all the plugins from a folder?

    For example i am updating the code of a plugin. In this way the plugin will not be registered again and the new code will not be in use.

    On the Ftrack server side we are checking every X minutes if there is new code pushed, and if it is, then it is re-launching the actions.

    Is it possible to do something similar for the Ftrack-Connect?


  5. If I create a new version and then I query the asset again, then the new version is not included in the asset['versions'].

    Example:

    asset = session.query("Asset where versions.task.id is '{0}'".format(task['id'])).one()
    print len(asset['version'])
    
    session.create('AssetVersion',
                   {'asset': asset,
                    'task': task,
                    'version': 13,
                    'status': status,
                    }
                   )
    session.commit()
    
    asset = session.query("Asset where versions.task.id is '{0}'".format(task['id'])).one()
    print len(asset['version'])
    
    -------
    Returns
    2
    2

     


  6. Hi all,

    I have a shot queried from DB via ftrack_api. I update a custom attribute of the respective shot. Then, in the same session, I query the shot again.

    The custom attribute of the respective shot is not updated even after I queried the shot again.

    Please find below an example:

        def test_query_custom_attributes(self):
    
            def update_custom_attribute(test_asset):
                new_session = ftrack_api.Session()
                same_test_asset = new_session.query("AssetBuild where id is '{0}'".format(test_asset["id"])).one()
                same_test_asset['custom_attributes']['delivery_name'] = "unittest"
                new_session.commit()
    
            test_asset = self._session.query("AssetBuild").first()
            delivery_name = test_asset['custom_attributes']['delivery_name']
    
            update_custom_attribute(test_asset)
    
            test_asset = self._session.query("AssetBuild where id is '{0}'".format(test_asset["id"])).one()
            new_delivery_name = test_asset['custom_attributes']['delivery_name']
    
            self.assertNotEqual(delivery_name, new_delivery_name)
    
            self._session.cache.clear()
            test_asset = self._session.query("AssetBuild where id is '{0}'".format(test_asset["id"])).one()
            new_delivery_name = test_asset['custom_attributes']['delivery_name']
            self.assertNotEqual(delivery_name, new_delivery_name)

    Clearing the cache and fetching the shot again from the database works.


  7. No, It doesn't. 

    Instead clearing the cache and querying the data again works.

    > print len(user['user_security_roles'])
    2
    > del user['user_security_roles']
    > user = get_ftrack_user(username="unittest_artist")
    > print len(user['user_security_roles'])
    2
    > session.cache.clear()
    > user = get_ftrack_user(username="unittest_artist")
    > print len(user['user_security_roles'])
    1

     


  8. As a workaround we run a script every X minutes which adds the uses added only to the groups to the project, too.

    """
    @package bin.check_projects_members
    @brief Check if the members of the projects have been added to the project.
    @details If the user has been added to the project group, but not to the project,
             then we need to add him/her to the project
    
    @author remusav
    """
    import logging
    import ftrack_session_manager
    
    
    log = logging.module_logger(__name__)
    session = ftrack_session_manager.main_session
    
    
    def get_grouped_users(project):
        """
        @param project: Ftrack Project
        @return list() of all grouped users from the project
        """
        grouped_users = []
        for allocation in project['allocations']:
            user_or_group = allocation['resource']
            if user_or_group.entity_type == "Group":
                for membership in user_or_group['memberships']:
                    grouped_users.append(membership['user'])
        return grouped_users
    
    
    def get_project_users(project):
        """
        @param project: Ftrack Project
        @return list() of all users added to the project
        """
        users = []
        for allocation in project['allocations']:
            user_or_group = allocation['resource']
            if user_or_group.entity_type == "User":
                users.append(user_or_group)
        return users
    
    
    def add_user_to_project(user, project):
        """
        Add the user to the Ftrack project
        @param user: Ftrack user
        @param project: Ftrack project
        """
        try:
            session.create("Appointment",
                           {"context": project,
                            "resource": user,
                            "type": "allocation"
                            })
            session.commit()
            log.info("user '{0}' added to project '{1}'".format(user['username'], project['name']))
        except Exception, e:
            session.rollback()
            log.error("user '{0}' couldn't be added to project '{1}'".format(user['username'], project['name']))
            log.error(e)
    
    
    def main():
        """
        Main function.
        """
        projects = session.query("Project where status is 'active'").all()
        for project in projects:
            grouped_users = get_grouped_users(project=project)
            project_users = get_project_users(project=project)
            users_not_assigned_to_project = set(grouped_users) - set(project_users)
    
            for user in users_not_assigned_to_project:
                add_user_to_project(user, project)
    
    
    if __name__ == '__main__':
        main()