Get default parameters for command

Get default parameters for command

joshua_e_mock
Contributor Contributor
607 Views
5 Replies
Message 1 of 6

Get default parameters for command

joshua_e_mock
Contributor
Contributor

Hi all,

 

Is there a way to list the default parameters for a given command in Maya using Python or the Maya API? For example, I want to create a method where a user can pass keyword arguments for the construction of an object (say a simple curve), but I want to make sure that in the construction of the settings that the user passes valid parameters - as seen on line 9 of the following example code.

 

def create_curve(**kwargs):
    # set the default settings
    settings = {'degree': 1,
                'point': ((0, 20, 0), (0, 0, 0)),
                'knot': (0, 1)}
    # extract settings from keyword arguments
    if kwargs:
        for key, value in kwargs.items():
            # TODO ensure that the key being passed is a valid parameter of the curve command
            settings[key] = value
    crv = pm.curve(**settings)
    return crv

 

 

Accepted solutions (2)
608 Views
5 Replies
Replies (5)
Message 2 of 6

Kahylan
Advisor
Advisor

Hi!

 

There isn't really an easy way to do this, since python variables are dynamic and can change type on the fly there isn't really a "check if this variable is the right typ" command.

 

You need to know what type your value should be and then run a check to see if that is correct.

You can use the type() command to check what type your variable is, and if that type doesn't line up with what you want it to be raise an error.

alternatively since you know the variable type, and lists and tuples are pretty much interchangable in python when it comes to maya, you could also use the isinstance command, to directly get a true or false query.

https://www.w3schools.com/python/ref_func_isinstance.asp

 

But honestly, probably the easiest way to do this, is to run the part of your function where the types of those variables are necessary inside a try and except statement:

try:
    Part that needs the kwargs
except TypeError:
    cmds.error("one of the keywordarguments is incorrect type")

This is less accurate as it doesn't give you the exact keyword argument that is wrong, but it also requires a lot less coding...

 

I hope it helps!

Message 3 of 6

joshua_e_mock
Contributor
Contributor

Thanks Kahylan

 

While that is helpful for other techniques, I'm more looking for a solution that would allow me to identify the valid flags for a given command. For example, if I wanted to make sure that my user had the correct keyword arguments to build a curve, I'd like to make sure that the keys in the kwargs correspond to a valid flag for the command as listed in the PyMEL documentation for curve.

 

I could create a tuple of flags for each command I want to provide functionality for and check against that, but that is labor intensive and bulky. I feel like it should be something that you can find dynamically either through the Maya API or PyMEL.

Message 4 of 6

Kahylan
Advisor
Advisor
Accepted solution

With functions like the pm.curve that have a set default value for each keyword argument, this can be done using try and except as well:

def create_curve(**kwargs):
    # set the default settings
    settings = {'degree': 1,
                'point': ((0, 20, 0), (0, 0, 0)),
                'knot': (0, 1)}
    # extract settings from keyword arguments
    if kwargs:
        for key, value in kwargs.items():
            try:
                crv = pm.curve(key = value)
                cmds.delete(crv)
                settings[key] = value
                
            except TypeError:
                pass
            
    crv = pm.curve(**settings)
    return crv

This only works if the function has provided default values for als kwargs, also it is a bit dirty since the function is run for every kwarg seperately to see if it exists.

 

Now, for your own functions, you can use the inspect command:

https://docs.python.org/3/library/inspect.html

 

But I have found that for more complex OOP based 3rd party functions this won't really work, as they often define the keyword arguments in the class and then just pass them to the functions as needed using **kwargs. This is also the case for pymel.core.curve in our example, so you wont get any keyword arguments or kward default values by inspecting it. Also inspect can only provide keyword arguments on native python functions, so builtin functions like all the commands in the cmds library wont work with it.

 

Depending on how many different commands you need to do this for. Having a dictionary with the command as key and a list of flags as the value, with functionality to read this out is probably the easier approach.

 

I hope it helps!

Message 5 of 6

joshua_e_mock
Contributor
Contributor

Thanks Kahylan,

 

Your suggestion is the best possible solution. I had tried the inspect method before, but it never gave me a list of flags, but the return wasn't what I needed. 

Message 6 of 6

joshua_e_mock
Contributor
Contributor
Accepted solution

I was doing some playing around with the idea of scanning the PyMEL documentation website to obtain these command flags and produced this method. Feel free to use it.

 

def get_pymel_core_command_flags(core_type='general', command='addAttr'):
    from urllib.request import urlopen

    pymel_document_base = 'https://help.autodesk.com/cloudhelp/2017/ENU/Maya-Tech-Docs/PyMel/generated/functions/'
    search = f'pymel.core.{core_type}/pymel.core.{core_type}.{command}.html'

    link = f'{pymel_document_base}{search}'
    flags = list()
    attr_prompt = '<span class="pre">'
    attr_end = '</span>'
    with urlopen(link) as webpage:
        for line in webpage:
            line = line.strip()
            line = line.decode('utf-8')
            if line:
                if attr_prompt in line:
                    start = line.index(attr_prompt) + len(attr_prompt)
                    end = line.index(attr_end, start)
                    flag = line[start:end]
                    if '.' not in flag and flag:
                        flags.append(flag)
    return flags