Search code examples
pythonlistreplacemaya

How to replace individual strings in a list with variables?


I'm making a script to make a naming convention in python for the program maya. I'm going to use it to name all the objects created by my scripts.

For example, lets take a left knee joint. The script will pass something like this ("bind", "shoulder", "left", "joint") to another module into the variables (prefix, name, side, obj_type). This input will then run through a user dictionary to check for existing values and change to a new value, if nothing is found it returns original value. For example, "joint" would turn into "jnt".

The user will input something like (prefix_,name_,SIDE_,obj_type,01)

I need it so that it will check if anything in the user input exists in the variable name. For example, if it finds any of the variable names in the users input (such as "prefix"), replace whatever is contained within the variable prefix at the index of where it is. Also, anything not found within the string will be left alone, like the "01", which will simply be added onto every name.

for example, the following above would return this "bn_shoulder_L_jnt01"

Also, if something is capitalized, like the first letter, or all letters, i want it to automatically capitalize the letters passed. Which is why typing SIDE_ would turn the "l" into "L".

I want this to be as flexible as possible, but my current trouble is getting it to replace the variables into the existing string if it finds the value. I've tried thinking of a couple things but haven't come up with much. Here is my code:

Also i currently have the users input passed to the class in the init. Will it work and be usable throughout the module? I'm still not 100% sure about how init is supposed to be used, but i wanted when the user inputs the naming convention it will be available in memory whenever it is needed.

Edited Code:

from string import Template

class Name:

    def __init__(self, user_conv):
        self.user_conv = user_conv


    def user_dict(self, word):
        """Matches given word with a dictionary, and returns converted abbreviated word.

        Keyword Arguments:
        string -- given string to be converted
                  example: joint > jnt
        """

        # prefixes
        user_library = {
        'bind' : 'bn',
        'driver' : 'drv',

        # side
        'back' : 'b',
        'down' : 'd',
        'front' : 'f',
        'left' : 'l',
        'right' : 'r',
        'up' : 'u',

        # obj_type
        'cluster' : 'clstr',
        'control' : 'ctrl',
        'curve' : 'crv',
        'effector' : 'efctr',
        'group' : 'grp',
        'ikHandle' : 'ikH',
        'joint' : 'jnt',
        'locator' : 'loc',
        'nurbs' : 'geo',
        'orientConstraint' : 'orCnstr',
        'parentConstraint' : 'prntCnstr',
        'pointConstraint' : 'ptCnstr',
        'polyMesh' : 'geo',

        # utilities
        'addDoubleLinear' : 'adl',
        'blendColors' : 'blndClr',
        'BlendTwoAttr' : 'b2a',
        'chooser' : 'chsr',
        'clamp' : 'clmp',
        'condition' : 'cn',
        'curveInfo' : 'crvI',
        'diffuse' : 'diffuse',
        'displacement' : 'displ',
        'multiplyDivide' : 'mdv',
        'normal' : 'normal',
        'place2d' : 'p2d',
        'plusMinusAverage' : 'pma',
        'reverse' : 'rv',
        'setRange' : 'sr',
        'shader' : 'shdr',
        'shadingGroup' : 'SG',
        'specular' : 'spec',
        'transparency' : 'trans',

        # sequential bones
        'arm' : 'arm',
        'fingser' : 'finger',
        'index' : 'index',
        'leg' : 'leg',
        'limb' : 'limb',
        'middle' : 'middle',
        'pinky' : 'pinky',
        'ring' : 'ring',
        'spine' : 'spine',
        'toe' : 'toe',
        'thumb' : 'thumb',

        #
        'ankle' : 'ankle',
        'ball' : 'ball',
        'breast' : 'breast',
        'chest' : 'chest',
        'clavicle' : ' clavicle',
        'elbow' : 'elbow',
        'end' : 'e',
        'head' : 'head',
        'hair' : 'hair',
        'knee' : 'knee',
        'neck' : 'neck',
        'pelvis' : 'pelvis',
        'root' : 'root',
        'shoulder' : 'shoulder',
        'tail' : 'tail',
        'thigh' : 'thigh',
        'wrist' : 'wrist'
        }

        if word in user_library:
            abbrevWord = user_library[word]
        else:
            abbrevWord = word

        return [abbrevWord]

    def convert(self, prefix, name, side, obj_type):
        """Converts given information about object into user specified naming convention.

        Keyword Arguments:
        prefix -- what is prefixed before the name
        name -- name of the object or node
        side -- what side the object is on, example 'left' or 'right'
        obj_type -- the type of the object, example 'joint' or 'multiplyDivide'
        """
        self.prefix = self.user_dict(prefix)
        self.name = self.user_dict(name)
        self.side = self.user_dict(side)
        self.obj_type = self.user_dict(obj_type)

        print '%s, %s, %s, %s' %(prefix, name, side, obj_type)

        self.new_string = Template (self.user_conv.lower())
        self.subs = {'prefix': prefix, 'name': name, 'side': side, 'obj_type': obj_type}
        self.new_string.substitute(**self.subs)

        print new_string

        return new_string

test code:

    # test file to test naming convention to see if its functioning properly

    import neo_name
    reload(neo_name)

def ui_test():
    """types user can input
    #prefix
    #name
    #side
    #type
    constants (such as 01, present in ALL objects/nodes/etc.)
    """
    user_conv = '${prefix}_${name}_${side}_${obj_type}${01}'

    name = neo_name.Name(user_conv)
    name.convert('bind', 'shoulder', 'left', 'joint')

ui_test()

Getting this error now, not sure what to make of it: bind, shoulder, left, joint Traceback (most recent call last): File "C:\Users\Gregory\Documents\Gregory's Folder\Artwork\3D Scripts_MyScripts\neoAutoRig\scripts\test_neo_name.py", line 19, in ui_test() File "C:\Users\Gregory\Documents\Gregory's Folder\Artwork\3D Scripts_MyScripts\neoAutoRig\scripts\test_neo_name.py", line 17, in ui_test name.convert('bind', 'shoulder', 'left', 'joint')

File "C:\Users\Gregory\Documents\Gregory's Folder\Artwork\3D Scripts_MyScripts\neoAutoRig\scripts\neo_name.py", line 133, in convert self.new_string.substitute(prefix = prefix, name = name, side = side, obj_type = obj_type) File "C:\Program Files\Autodesk\Maya2014\bin\python27.zip\string.py", line 172, in substitute File "C:\Program Files\Autodesk\Maya2014\bin\python27.zip\string.py", line 169, in convert File "C:\Program Files\Autodesk\Maya2014\bin\python27.zip\string.py", line 146, in _invalid ValueError: Invalid placeholder in string: line 1, col 38


Solution

  • This is also a good application for the python string.Template class:

    from string import Template

    t = Template ("${prefix}_${side}_${limb}")
    t.substitute(prefix ='character', side='R', limb='hand')
    >>> 'character_R_hand'
    

    You can get fancier by treating separators as conditional (default them to ''), enforcing capitalization rules, etc. Template.substitute take either flags (as in the example above) or a dictionary:

    t = Template ("${prefix}_${side}_${limb}")
    subs = {'prefix':'dict', 'side':'L', 'limb':'bicep'}
    t.substitute(**subs)
    >>> 'dict_L_hand'