Shotgun displaying API Script name instead of username

Hello,

We are using a script when submitting our Nuke work to Deadline. Shotgun is displaying the name of the API script as expected and the name of the user can be seen in details of the job in Shotgun. However, we want to see the name of the user instead of “Nuke Uploader” (which is the name of our API script). Is there a way we can tweak the script to display the name of the user who sent the render job instead of the name of the script that executed it?

Thanks!!

I have asked the devs to discuss this and see what we can do on this.

Hello,

I talked with one of our devs and they advised that you can use UserName=[name of user] in the Job Info file (the first file created by their submitter that is passed to deadlinecommand). Since it sounds like you have a custom submission process, you can refer to the Manual Job Submission docs for more info at docs.thinkboxsoftware.com/produc … -info-file and if you do this, your jobs should have the right submitting user, instead of the name of the script. Can you try that for me?

Hi,
you can fix it by overiding the [“created_by”] in the data variable.So preaty much correct the addnewversion function and add extra variable called userId for example so now you can use the ShotgunUtils.GetUser(userName,shotgunPath) to get the id needed then just create “created_by”: userId in the data variable,which will create link kym that user :>.I presume it will work since I I had to write custom version uploader for shotgun and it worked that way so I`m guesing it will be the same with the one provided in deadline xD.

Hope this helps.

Veselin Georgiev Gyurov.

Hello,
Thanks for all the answers. I wanted to make this work for every single time I post a work in deadline and we are not using Job Info File. Is it possible to create a job info file which would work any time we submit a work?

I also tried the other method and added the line:
userId = sg.GetUser(userName, shotgunPath)

to AddNewVersion function. But I didn’t understand what you mean by “data variable”. Where can I find that? And do I only need to write:

“created_by”: userId

Thanks in advance!

Hi,
Really sorry I didnt explained it very good :>.The data is the dictionary that is used to supply shotgun with the information for the version creation proicess.This is the default addnewversion in ShotgunUtils:

[code]def AddNewVersion( userName, taskId, projectId, entityId, entityType, version, description, frameList, frameCount, outputPath, shotgunPath=None, jobID="" ):

ini = GetIniFileData( shotgunPath )

sg = GetShotgun( shotgunPath )

user = sg.find_one("HumanUser",filters=[["login","is",userName]],fields=['login','name'])

startFrame = -1
endFrame = -1
#extracts all the individual frame numbers from the list, ignoring any step/interleaving numbers
frames = re.findall( "(?:[^xi(step)(by)(every)\d]|^)(\d+)", str(frameList) )

for frame in frames:
    if startFrame == -1 or frame < startFrame:
        startFrame = frame
    
    if endFrame == -1 or frame > endFrame:
        endFrame = frame

data = { 
    'user': user,
    'code': version,
    'description': description,
    }
    
if ini.get('VersionEntityPathToFramesField', "") != "":
    data[ ini['VersionEntityPathToFramesField'] ] = outputPath

if ini.get('VersionEntityFrameRangeField', "") != "":
    data[ ini['VersionEntityFrameRangeField'] ] = frameList

if ini.get('VersionEntityFrameCountField', "") != "":
    data[ ini['VersionEntityFrameCountField'] ] = frameCount

if ini.get('VersionEntityFirstFrameField', "") != "":
    data[ ini['VersionEntityFirstFrameField'] ] = int(startFrame)

if ini.get('VersionEntityLastFrameField', "") != "":
    data[ ini['VersionEntityLastFrameField'] ] = int(endFrame)

if ini.get('VersionEntityJobIDField', "") != "":
    data[ ini['VersionEntityJobIDField'] ] = jobID
    
if ( taskId >= 0 and ini.get('VersionEntityTaskField', "") != "" ) :
    data[ini['VersionEntityTaskField']] = {'type':'Task', 'id':taskId}
    task = sg.find_one('Task', [['id','is',taskId]], ['entity', 'project'])
    data['project'] = task['project']
    data['entity'] = task['entity']
else :	
    data['project'] = {'type':'Project', 'id':projectId}
    data['entity'] = {'type':entityType, 'id':entityId}
new_version = sg.create('Version', data)


return SafeDecode( new_version )[/code]

If you are using it you can add extra variable lets say userID for the function to use so it becomes something like this:
def AddNewVersion(userID, userName, taskId, projectId, entityId, entityType, version, description, frameList, frameCount, outputPath, shotgunPath=None, jobID="" )

then add that to the data variable as typing:
“created_by”:userID

Heres how my data variable look like:

[code] data = {
“project”:get_proj_id,
“code”: str(version_name),
“description”: version_description,
“sg_status_list”: “rev”,
“user”: get_user_id,
“entity”:get_shot_id,
“sg_upload_comment”: version_description,
“sg_path_to_frames”: file_for_draft,
“frame_count” : frame_count_for_SG,
“sg_first_frame” : get_1st_frame,
“sg_last_frame” : get_last_frame,
“frame_range” : frame_range,
“sg_task” : get_task_id,
“sg_path_to_movie”: out_file,
“created_by” :get_user_id,
}

ver=sg.create("Version",data)

[/code]

Hope this helps.

Veselin Georgiev Gyurov.

Hello,

I understood what you meant now. Thanks for the detailed answer. I’ve made that change however that is giving a syntax error because of “created_by”. It seems that I need to make few more changes. Do you have any clue what those might be?

Thanks!

Hi,
did you put “,” to separate it like:
“sg_path_to_movie”: out_file[size=150],[/size]
“created_by” :get_user_id,
?

Hello,

I just realised that mistake and fixed it but it still says “Nuke Uploader” in Shotgun’s website. We are not changing anything related to the name of the API script. How do we expect to see the change on script name by adding a “data variable”?

Hi,

no man what this data variable is doing is its giving SG the information for the version creation.If you go to version info in SG you will see that theres a line called “Created by” and you will see the name of your script there,however the name of this line in SG is [“created_by”] which mean that if you put it while creating the version it should overide the script link and it will put link to the user provided by its ID.If its ok can you share the code yo uare using for creating the version :>.

Oh!, I see :smiley:. I’m sending the code below. I don’t think it’s because of the single or double quote marks. I’ve tried both user and userID for “created_by”.

Thanks!

    ini = GetIniFileData( shotgunPath )

    sg = GetShotgun( shotgunPath )
    
    user = sg.find_one("HumanUser",filters=[["login","is",userName]],fields=['login','name'])

    userID = sg.GetUser(userName, shotgunPath)
    
    startFrame = -1
    endFrame = -1
    #extracts all the individual frame numbers from the list, ignoring any step/interleaving numbers
    frames = re.findall( "(?:[^xi(step)(by)(every)\d]|^)(\d+)", str(frameList) )
    
    for frame in frames:
        if startFrame == -1 or frame < startFrame:
            startFrame = frame
        
        if endFrame == -1 or frame > endFrame:
            endFrame = frame
    
    data = { 
        'user': user,
        'code': version,
        'description': description,
        'created_by': user
        }

in this here I can see that you are pointing to wrong variable ->‘created_by’: user should be ‘created_by’: userID in your case

Changed it to userID, but it’s still the same.

This is very strange because I just tested it and it worked O_o:

[code]def AddNewVersion_test( userID,version, description,projectID,shotgunPath=None):

#ini = GetIniFileData( shotgunPath )
print shotgunPath
sg = GetShotgun( shotgunPath )

#user = sg.find_one("HumanUser",filters=[["login","is",userName]],fields=['login','name'])


data = { 
    'project':projectID,
    'user': userID,
    'code': version,
    'description': description,
    'created_by' :userID,
    }

ver=sg.create("Version",data)

return SafeDecode( ver) [/code]  

I know it sound stupid but since you are modifying ShotgunUtils can you try to restart deadline monitor? xD.

Hello,

I restarted but it didn’t changed anything as expected. And I can’t try to restart our server any time soon. But I highly don’t think that is the reason. I just tried after changing the command line section of the ShotgunUtils but it’s still the same.

Thanks for everything

Hmmm, it should definitely work. Can you post the entire modified ShotgunUtils.py file, so I can have a look at and test? I can then just fix anything that might be wrong with it and post and updated one for you to drop in.

I should also mention that this is definitely something that’d be worth adding to our default file as well, so we’ll probably add that in for future versions on our end too :slight_smile:

Cheers,
Jon

Hello,

I think the problem is caused because of line, but I have no explanation why:

    userID = sg.GetUser(userName, shotgunPath)

The entire modified ShotgunUtils.py is below:

import sys
import os
import re

import shotgun_api3.shotgun

def GetIniFileData( shotgunPath=None ) :
    
    if shotgunPath == None:
        shotgunPath = os.path.dirname( sys.argv[0] )
    
    iniFilename = os.path.join( shotgunPath, "Shotgun.dlinit" )
    iniFile = open( iniFilename, "r" )
    fileIn = iniFile.read()
    ini = fileIn.splitlines()
    iniFile.close()
    
    iniEntries = dict()
    for currLine in ini:
        line = currLine.replace( "\n", "" ).replace( "\r", "" )
        equalIndex = line.find( "=" )
        if equalIndex >= 0:
            if equalIndex < (len(line) - 1):
                if line[:equalIndex].find( "Enabled" ) != -1:
                    # This is a hack to get around a potential encoding problem.
                    iniEntries[ "Enabled" ] = line[equalIndex+1:]
                else:
                    iniEntries[line[:equalIndex]] = line[equalIndex+1:]
                #iniEntries[line[:equalIndex]] = line[equalIndex+1:]
            else:
                iniEntries[line[:equalIndex]] = ""
            
    return iniEntries
    
def GetShotgun( shotgunPath=None ):
    if shotgunPath == None:
        shotgunPath = os.path.dirname( sys.argv[0] )
        
    ini = GetIniFileData( shotgunPath )
    
    url = ini['ShotgunURL']
    name = ini['ShotgunScriptName']
    key = ini['ShotgunScriptKey']
    proxy = ini['ShotgunProxy']
    if proxy == "":
        proxy = None
        
    sgObject = shotgun_api3.shotgun.Shotgun( url, name, key, True, proxy, connect=False )
    
    try:
        noSslValidationString = ini['ShotgunNoSslValidation'].lower()
        noSslValidation = (noSslValidationString == "1" or noSslValidationString == "true")
        sgObject.config.no_ssl_validation = noSslValidation
    except:
        pass
    
    return sgObject
    
    #return shotgun_api3.shotgun.Shotgun( url, name, key, True, proxy )

#Utility function to safely try to decode strings (or dict/list contents)
def SafeDecode( obj, useEncoding='utf-8' ):
    try:
        if isinstance( obj, unicode ):
            #already unicode, just reutnr it
            return obj
        elif isinstance( obj, str ):
            #it's a str, decode it
            return obj.decode( useEncoding )
        elif isinstance( obj, dict ):
            #recursively convert contents
            for k, v in obj.iteritems():
                obj[k] = SafeDecode( v )
        elif isinstance( obj, list ):
            #recursively convert contents
            for i in range( len(obj) ):
                obj[i] = SafeDecode( obj[i] )
        else:
            #last ditch attempt
            return unicode( obj, encoding=useEncoding )
    except:
        pass

    return obj
    
    
def GetShotgunAPIVersion():
    if hasattr( shotgun_api3.shotgun, '__version__' ):
        return shotgun_api3.shotgun.__version__
    else:
        return ""

def GetUserNames( shotgunPath=None ):
    userNames = []
    
    sg = GetShotgun( shotgunPath )
    users = sg.find("HumanUser",filters=[], fields=['login'], order=[{'field_name':'login','direction':'asc'}])
    for user in users:
        userNames.append( user['login'] )
    userNames.sort()
    
    return SafeDecode( userNames )
    
def GetUser( loginName, shotgunPath=None ):
    
    sg = GetShotgun( shotgunPath )
    
    user = sg.find_one("HumanUser", filters=[["login","is",loginName]], fields=['login','name'])
    return SafeDecode( user )

def GetProjects( shotgunPath=None ):
    
    sg = GetShotgun( shotgunPath )
    projects = []
    projects = sg.find('Project', filters=[['sg_status', 'is_not', 'Archive'],['name', 'is_not', 'Template Project']], fields=['name'], order=[{'field_name':'name','direction':'asc'}])
    return SafeDecode( projects )

def GetShotsAndAssets( projectID, shotgunPath=None ):
    
    sg = GetShotgun( shotgunPath )
    project = {'type' : 'Project', 'id' : projectID}
    assets = []
    assets = sg.find('Asset', filters=[['project', 'is', project], ['sg_status_list', 'is_not', 'omt']], fields=['code'], order=[{'field_name':'code','direction':'asc'}])
    shots = []
    shots = sg.find('Shot', filters=[['project', 'is', project], ['sg_status_list', 'is_not', 'omt']], fields=['code','sg_sequence'], order=[{'field_name':'sequence','direction':'asc'},{'field_name':'name','direction':'asc'}])
    return SafeDecode( shots ), SafeDecode( assets)

def GetShotsAssetsAndElements( projectID, shotgunPath=None ):
    shots, assets = GetShotsAndAssets( projectID, shotgunPath )
    
    sg = GetShotgun( shotgunPath )
    project = { 'type' :'Project', 'id' : projectID }
    elements = []
    
    #This blows up if Elements aren't turned on
    if 'Element' in sg.schema_entity_read():
        elements = sg.find('Element', filters=[['project', 'is', project], ['sg_status_list', 'is_not', 'omt']], fields=['code'], order=[{'field_name':'code','direction':'asc'}])
    
    return SafeDecode( shots ), SafeDecode( assets ), SafeDecode( elements )


def GetTasks( userName, draftField = None, shotgunPath=None ):
    tasks = []
    return_fields = ['content','project','entity']
    
    if draftField == None:
        ini = GetIniFileData( shotgunPath )
        draftField = ini['DraftTemplateField']
    
    #The Shotgun API doesn't like blank fields anymore, so check for that before tossing it in
    if draftField != None and draftField.strip() != "":
        return_fields.append( draftField )
    
    sg = GetShotgun( shotgunPath )
    
    userEntry = sg.find_one("HumanUser",filters=[["login","is",userName]],fields=['login','name'])
    if userEntry:
        tasks = sg.find("Task", filters=[['sg_status_list', 'is', 'ip'],["task_assignees", "is", userEntry]], fields=return_fields, order=[{'field_name':'project','direction':'asc'},{'field_name':'entity','direction':'asc'},{'field_name':'content','direction':'asc'}])
        tasks.extend( sg.find("Task", filters=[['sg_status_list', 'is', 'rdy'],["task_assignees", "is", userEntry]], fields=return_fields, order=[{'field_name':'project','direction':'asc'},{'field_name':'entity','direction':'asc'},{'field_name':'content','direction':'asc'}]) )
        
        #This is a more comprehensive task filter.  Will return everything all tasks that are not 'Final' or 'Complete'
        #tasks = sg.find("Task", filters=[['sg_status_list', 'is_not', 'fin'],['sg_status_list', 'is_not', 'cmpt'],["task_assignees", "is", userEntry]], fields=['content','project','entity',draftField])
        
        #standardize where the draft template is stashed, so we don't have to look it up all the time
        for task in tasks:
            task["draftTemplate"] = task.get( draftField, "" )
    
    return SafeDecode( tasks )

def GetVersions( entityType, entityID, shotgunPath=None ):
    
    ini = GetIniFileData( shotgunPath )
    pathField = ini['VersionEntityPathToFramesField']
    firstFrameField = ini['VersionEntityFirstFrameField']
    lastFrameField = ini['VersionEntityLastFrameField']
    
    versions = []
    
    sg = GetShotgun( shotgunPath )
    entity = { 'type' : entityType, 'id' : entityID }
    versions = sg.find("Version",[['entity', 'is', entity]],['code', pathField, firstFrameField, lastFrameField, 'description'])
    return SafeDecode( versions )

def GetVersion( versionID, shotgunPath=None ):
    ini = GetIniFileData( shotgunPath )
    pathField = ini['VersionEntityPathToFramesField']
    firstFrameField = ini['VersionEntityFirstFrameField']
    lastFrameField = ini['VersionEntityLastFrameField']
    jobIDField = ini.get('VersionEntityJobIDField', '')
    draftField = ini.get('DraftTemplateField', '')

    fieldFilter = ['code','id','project','entity','user',pathField,firstFrameField,lastFrameField,'description']
    if jobIDField != '':
        fieldFilter.append( jobIDField )

    if draftField:
        fieldFilter.append( 'sg_task.Task.' + draftField )
    
    sg = GetShotgun( shotgunPath )
    version = sg.find_one('Version', [['id','is',versionID]], fieldFilter)
    if version and version['user'] and ('name' in version['user']):
        user = sg.find_one('HumanUser',[['name','is',version['user']['name']]],['login'])
        version['user']['login'] = user['login']
    return SafeDecode( version )
    
def AddNewVersion( userName, taskId, projectId, entityId, entityType, version, description, frameList, frameCount, outputPath, shotgunPath=None, jobID="" ):
    
    ini = GetIniFileData( shotgunPath )

    sg = GetShotgun( shotgunPath )
    
    user = sg.find_one("HumanUser",filters=[["login","is",userName]],fields=['login','name'])
    userID = sg.GetUser(userName, shotgunPath)
    startFrame = -1
    endFrame = -1
    #extracts all the individual frame numbers from the list, ignoring any step/interleaving numbers
    frames = re.findall( "(?:[^xi(step)(by)(every)\d]|^)(\d+)", str(frameList) )
    
    for frame in frames:
        if startFrame == -1 or frame < startFrame:
            startFrame = frame
        
        if endFrame == -1 or frame > endFrame:
            endFrame = frame
    
    data = { 
        'user': user,
        'code': version,
        'description': description,
        'created_by': userID
        }
        
    if ini.get('VersionEntityPathToFramesField', "") != "":
        data[ ini['VersionEntityPathToFramesField'] ] = outputPath
    
    if ini.get('VersionEntityFrameRangeField', "") != "":
        data[ ini['VersionEntityFrameRangeField'] ] = frameList
    
    if ini.get('VersionEntityFrameCountField', "") != "":
        data[ ini['VersionEntityFrameCountField'] ] = frameCount
    
    if ini.get('VersionEntityFirstFrameField', "") != "":
        data[ ini['VersionEntityFirstFrameField'] ] = int(startFrame)
    
    if ini.get('VersionEntityLastFrameField', "") != "":
        data[ ini['VersionEntityLastFrameField'] ] = int(endFrame)
    
    if ini.get('VersionEntityJobIDField', "") != "":
        data[ ini['VersionEntityJobIDField'] ] = jobID
        
    if ( taskId >= 0 and ini.get('VersionEntityTaskField', "") != "" ) :
        data[ini['VersionEntityTaskField']] = {'type':'Task', 'id':taskId}
        task = sg.find_one('Task', [['id','is',taskId]], ['entity', 'project'])
        data['project'] = task['project']
        data['entity'] = task['entity']
    else :	
        data['project'] = {'type':'Project', 'id':projectId}
        data['entity'] = {'type':entityType, 'id':entityId}
    
    #print data
    new_version = sg.create('Version', data)
    
    return SafeDecode( new_version )


def UpdateVersion( versionId, statusCode, shotgunPath=None ):
    sg = GetShotgun( shotgunPath )
    ini = GetIniFileData( shotgunPath )
    data = {ini['VersionEntityStatusField'] : statusCode}
    sg.update('Version', versionId, data)

def UpdateRenderTimeForVersion( versionID, avgRenderTime, totalRenderTime, shotgunPath=None ):
    sg = GetShotgun( shotgunPath )
    ini = GetIniFileData( shotgunPath )
    
    data = {}
    
    #append the relevant fields to the data dictionary
    avgTimeFieldName = ini['VersionEntityAverageTimeField']
    if ( avgRenderTime != None and avgTimeFieldName != None and avgTimeFieldName.strip() != "" ):
        data.update( { avgTimeFieldName : avgRenderTime } )
    
    totalTimeFieldName = ini['VersionEntityTotalTimeField']
    if ( totalRenderTime != None and totalTimeFieldName != None and totalTimeFieldName.strip() != "" ):
        data.update( { totalTimeFieldName : totalRenderTime } )
    
    #only upload if the fields are actually mapped
    if ( len( data.items() ) > 0 ):
        sg.update( 'Version', versionID, data )

def UploadMovieToVersion( versionID, path, shotgunPath=None ):
    sg = GetShotgun( shotgunPath )
    ini = GetIniFileData( shotgunPath )
    
    pathToMovieField = ini['VersionEntityPathToMovieField']
    if ( pathToMovieField != None and pathToMovieField.strip() != "" ):
        data = { pathToMovieField : path }
        sg.update( 'Version', versionID, data )
    
    sg.upload( 'Version', versionID, path, ini['VersionEntityUploadMovieField'] )

def UploadFilmstripToVersion( versionID, path, shotgunPath=None ):
    sg = GetShotgun( shotgunPath )
    sg.upload_filmstrip_thumbnail( 'Version', versionID, path )
    
def UploadThumbnailToVersion( versionID, path, shotgunPath=None ) :
    sg = GetShotgun( shotgunPath )
    sg.upload_thumbnail( 'Version', versionID, path )
    
def CreateActionMenuItem ( title, entity, shotgunPath=None ) :
    
    sg = GetShotgun( shotgunPath )
    data = {
      "title":title,
      "url": "draft://submit_job_to_deadline",
      "list_order": 1,
      "entity_type": entity,
      "selection_required": True, 
    }
    if ( sg.find_one('ActionMenuItem', [['title', 'is', title]]) == None ) :
        sg.create('ActionMenuItem', data)
    
########################################################################
## This handles the case where the script is called from the command line.
########################################################################
#if len( sys.argv ) > 1:
if hasattr( sys, 'argv' ) and len( sys.argv ) > 1:
    arg = sys.argv[1]
    
    if arg == "CreateActionMenuItem":
        CreateActionMenuItem(sys.argv[2], sys.argv[3])
    
    if arg == "Users":
        userNames = GetUserNames()
        for userName in userNames:
            print( "%s" % userName  )
    
    if arg == "Projects":
        projects = GetProjects()
        for project in projects:
            print( "ProjectName=%s" % project['name'] )
            print( "ProjectID=%s" % project['id'] )
            print( "" )
            
    if arg == "ShotsAndAssets":
        projectID = int(sys.argv[2])
        shots,assets = GetShotsAndAssets(projectID)
        for shot in shots:
            print( "ShotCode=%s" % shot['code'] )
            print( "ShotID=%s" % shot['id'] )
            print( "" )
        for asset in assets:
            print( "AssetCode=%s" % asset['code'] )
            print( "AssetID=%s" % asset['id'] )
            print( "" )
            
    if arg == "Tasks" and len( sys.argv ) > 2:
        
        ini = GetIniFileData()
        draftField = ini['DraftTemplateField']
        
        userName = sys.argv[2]
        
        tasks = GetTasks( userName, draftField )
        for task in tasks:
            print( "TaskName=%s" % task['content'] )
            print( "TaskID=%s" % task['id'] )
            print( "DraftTemplate=%s" % task[draftField] )
            if task['project'] != None:
                print( "ProjectName=%s" % task['project']['name'] )
                print( "ProjectID=%s" % task['project']['id'] )
            if task['entity'] != None:
                print( "EntityName=%s" % task['entity']['name'] )
                print( "EntityType=%s" % task['entity']['type'] )
                print( "EntityID=%s" % task['entity']['id'] )
            print( "" )
    
    if arg == "Version" and len( sys.argv ) > 2:
    
        ini = GetIniFileData()
        versionID = int(sys.argv[2])
        version = GetVersion( versionID )
        print ("VersionCode=%s" % version['code'] )
        print ("VersionUser=%s" % version['user']['login'] )
        print ("VersionProjectID=%s" % version['project']['id'] )
        print ("VersionEntityType=%s" % version['entity']['type'] )
        print ("VersionEntityID=%s" % version['entity']['id'] )
        print ("")
        
    if arg == "Versions" and len( sys.argv ) > 3:
        ini = GetIniFileData()
        pathField = ini['VersionEntityPathToFramesField']
        firstFrameField = ini['VersionEntityFirstFrameField']
        lastFrameField = ini['VersionEntityLastFrameField']
        
        entityType = sys.argv[2]
        entityID = int(sys.argv[3])
        
        versions = GetVersions( entityType, entityID )

        for version in versions:
            print( "VersionCode=%s" % version['code'] )
            print( "VersionID=%s" % version['id'] )
            if ( pathField in version ) :
                print( "VersionPath=%s" % version[pathField] )
            else :
                print( "VersionPath=" )
            if ( firstFrameField in version ) :
                print( "VersionFirstFrame=%s" % version[firstFrameField] )
            else :
                print( "VersionFirstFrame=" )
            if ( lastFrameField in version ) :
                print( "VersionLastFrame=%s" % version[lastFrameField] )
            else :
                print( "VersionLastFrame=" )
            print( "" )
            
    if arg == "NewVersion" and len( sys.argv ) > 11:
        userName = sys.argv[2]
        taskId = int(sys.argv[3])
        projectId = int(sys.argv[4])
        entityId = int(sys.argv[5])
        entityType = sys.argv[6]
        version =sys.argv[7]
        description = sys.argv[8]
        frameList = sys.argv[9]
        frameCount = int(sys.argv[10])
        outputPath = sys.argv[11]
        
        new_version = AddNewVersion( userName, taskId, projectId, entityId, entityType, version, description, frameList, frameCount, outputPath )
        print( "New Shotgun version created with ID: %s" % new_version['id'] )
    
    if arg == "Update" and len( sys.argv ) > 3:
        versionId = int(sys.argv[2])
        statusCode = sys.argv[3]
        
        UpdateVersion( versionId, statusCode )

    if arg == "UpdateRenderTime" and len( sys.argv ) > 4:
        versionId = int(sys.argv[2])
        avgRenderTime = sys.argv[3]
        totalRenderTime = sys.argv[4]
        
        UpdateRenderTimeForVersion( versionId, avgRenderTime, totalRenderTime )

    if arg == "Upload" and len( sys.argv ) > 3:
        versionId = int(sys.argv[2])
        path = sys.argv[3]
        
        UploadMovieToVersion( versionId, path )
        
    if arg == "UploadThumbnail" and len( sys.argv ) > 3:
        versionId = int(sys.argv[2])
        path = sys.argv[3]

        UploadThumbnailToVersion( versionId, path )

Cheers!

Ah, right, I think I see the problem. You should just be able to swap this line:

    userID = sg.GetUser(userName, shotgunPath)

with this one instead:

    userID = user['id']

I think the rest is fine as is. Let me know if that works out for you!

Cheers,
Jon

Unfortunately that didn’t work out either. It doesn’t give any errors but uploading to Shotgun is not working. Only that userID line and the ‘created_by’ variable is added on top of the default script.

Ah, sorry, it seems the created_by parameter expects a full User object (at least in the version of Shotgun I’ve tested with).

Try the following dictionary definition:

    data = { 
        'user': user,
        'code': version,
        'description': description,
        'created_by': user
        }

I tested this in the script you gave me earlier, and it works for me:
Shotgun.png