Exemplo n.º 1
0
def py2melProc( function, returnType=None, procName=None, evaluateInputs=True, argTypes=None ):
    """This is a work in progress.  It generates and sources a mel procedure which wraps the passed
    python function.  Theoretically useful for calling your python scripts in scenarios where Maya
    does not yet support python callbacks.

    The function is inspected in order to generate a MEL procedure which relays its
    arguments on to the python function.  However, Python features a very versatile argument structure whereas
    MEL does not.

        - python args with default values (keyword args) will be set to their MEL analogue, if it exists.
        - normal python args without default values default to strings. If 'evaluteInputs' is True, string arguments passed to the
            MEL wrapper proc will be evaluated as python code before being passed to your wrapped python
            function. This allows you to include a typecast in the string representing your arg::

                myWrapperProc( "Transform('persp')" );

        - *args : not yet implemented
        - **kwargs : not likely to be implemented


    function
        This can be a callable python object or the full, dotted path to the callable object as a string.

        If passed as a python object, the object's __name__ and __module__ attribute must point to a valid module
        where __name__ can be found.

        If a string representing the python object is passed, it should include all packages and sub-modules, along
        with the function's name:  'path.to.myFunc'

    procName
        Optional name of the mel procedure to be created.  If None, the name of the function will be used.

    evaluateInputs
        If True (default), string arguments passed to the generated mel procedure will be evaluated as python code, allowing
        you to pass a more complex python objects as an argument. For example:

        In python:
            >>> import pymel.tools.py2mel as py2mel
            >>> def myFunc( arg ):
            ...    for x in arg:
            ...       print x
            >>> py2mel.py2melProc( myFunc, procName='myFuncWrapper', evaluateInputs=True )

        Then, in mel::
            // execute the mel-to-python wrapper procedure
            myFuncWrapper("[ 1, 2, 3]");

        the string "[1,2,3]" will be converted to a python list [1,2,3] before it is executed by the python function myFunc
    """

    function = _getFunction( function )

    funcName = function.__name__

    melCompile = []
    melArgs = []
    melArrayToStrDecls = []
    argList, defaults, description = getMelArgs(function)

    if argTypes:
        if isMapping(argTypes):
            pass
        elif isIterable(argTypes):
            tmp = argTypes
            argTypes = {}
            for i, argType in enumerate(tmp):
                argTypes[argList[i][0]] = argType
        else:
            raise ValueError, "argTypes must be iterable or mapping type"
        for argType in argTypes.values():
            if not isValidMelType(argType):
                raise TypeError, "%r is not a valid mel type: %s" % (argType, ', '.join(MELTYPES))
    else:
        argTypes = {}

    for arg, melType in argList:
        if melType == 'string':
            compilePart = "'\" + $%s + \"'" %  arg
            melCompile.append( compilePart )
        elif melType == None:
            melType = 'string'
            compilePart = "'\" + $%s + \"'" %  arg
            compilePart = r'eval(\"\"\"%s\"\"\")' % compilePart
            melCompile.append( compilePart )
        elif melType.count('[]'):
            melArrayToStrDecls.append( 'string $_%s ="("; int $i=0;for($i; $i<size($%s); $i++) { $_%s += ($%s[$i] + ",");  } $_%s += ")";' % (arg, arg, arg, arg, arg))
            melCompile.append( "'\" + $_%s + \"'" % arg )
        else:
            melCompile.append( "\" + $%s + \"" %  arg )

        if melType.count('[]'):
            melType = melType.replace('[]','')
            melArgs.append( '%s $%s[]' % (melType, arg) )
        else:
            melArgs.append( '%s $%s' % (melType, arg) )

    if procName is None:
        procName = funcName

    procDef = """global proc %s %s( %s ){ %s
    python("import %s; %s._functionStore[%r](%s)");}""" % ( returnType if returnType else '',
                                                            procName,
                                                            ', '.join(melArgs),
                                                            ''.join(melArrayToStrDecls),
                                                            __name__,
                                                            __name__,
                                                            repr(function),
                                                            ','.join(melCompile) )
    _functionStore[repr(function)] = function

    _mm.eval( procDef )
    return procName
Exemplo n.º 2
0
def py2melProc(function,
               returnType=None,
               procName=None,
               evaluateInputs=True,
               argTypes=None):
    """This is a work in progress.  It generates and sources a mel procedure which wraps the passed
    python function.  Theoretically useful for calling your python scripts in scenarios where Maya
    does not yet support python callbacks.

    The function is inspected in order to generate a MEL procedure which relays its
    arguments on to the python function.  However, Python features a very versatile argument structure whereas
    MEL does not.

        - python args with default values (keyword args) will be set to their MEL analogue, if it exists.
        - normal python args without default values default to strings. If 'evaluteInputs' is True, string arguments passed to the
            MEL wrapper proc will be evaluated as python code before being passed to your wrapped python
            function. This allows you to include a typecast in the string representing your arg::

                myWrapperProc( "Transform('persp')" );

        - *args : not yet implemented
        - **kwargs : not likely to be implemented


    function
        This can be a callable python object or the full, dotted path to the callable object as a string.

        If passed as a python object, the object's __name__ and __module__ attribute must point to a valid module
        where __name__ can be found.

        If a string representing the python object is passed, it should include all packages and sub-modules, along
        with the function's name:  'path.to.myFunc'

    procName
        Optional name of the mel procedure to be created.  If None, the name of the function will be used.

    evaluateInputs
        If True (default), string arguments passed to the generated mel procedure will be evaluated as python code, allowing
        you to pass a more complex python objects as an argument. For example:

        In python:
            >>> import pymel.tools.py2mel as py2mel
            >>> def myFunc( arg ):
            ...    for x in arg:
            ...       print x
            >>> py2mel.py2melProc( myFunc, procName='myFuncWrapper', evaluateInputs=True )

        Then, in mel::
            // execute the mel-to-python wrapper procedure
            myFuncWrapper("[ 1, 2, 3]");

        the string "[1,2,3]" will be converted to a python list [1,2,3] before it is executed by the python function myFunc
    """

    function = _getFunction(function)

    funcName = function.__name__

    melCompile = []
    melArgs = []
    melArrayToStrDecls = []
    argList, defaults, description = getMelArgs(function)

    if argTypes:
        if isMapping(argTypes):
            pass
        elif isIterable(argTypes):
            tmp = argTypes
            argTypes = {}
            for i, argType in enumerate(tmp):
                argTypes[argList[i][0]] = argType
        else:
            raise ValueError, "argTypes must be iterable or mapping type"
        for argType in argTypes.values():
            if not isValidMelType(argType):
                raise TypeError, "%r is not a valid mel type: %s" % (
                    argType, ', '.join(MELTYPES))
    else:
        argTypes = {}

    for arg, melType in argList:
        melType = argTypes.get(arg, melType)
        if melType == 'string':
            compilePart = "'\" + $%s + \"'" % arg
            melCompile.append(compilePart)
        elif melType == None:
            melType = 'string'
            compilePart = "'\" + $%s + \"'" % arg
            compilePart = r'eval(\"\"\"%s\"\"\")' % compilePart
            melCompile.append(compilePart)
        elif melType.count('[]'):
            melArrayToStrDecls.append(
                'string $_%s ="("; int $i=0;for($i; $i<size($%s); $i++) { $_%s += ($%s[$i] + ",");  } $_%s += ")";'
                % (arg, arg, arg, arg, arg))
            melCompile.append("'\" + $_%s + \"'" % arg)
        else:
            melCompile.append("\" + $%s + \"" % arg)

        if melType.count('[]'):
            melType = melType.replace('[]', '')
            melArgs.append('%s $%s[]' % (melType, arg))
        else:
            melArgs.append('%s $%s' % (melType, arg))

    if procName is None:
        procName = funcName

    procDef = """global proc %s %s( %s ){ %s
    python("import %s; %s._functionStore[%r](%s)");}""" % (
        returnType if returnType else '', procName,
        ', '.join(melArgs), ''.join(melArrayToStrDecls), __name__, __name__,
        repr(function), ','.join(melCompile))
    _functionStore[repr(function)] = function

    _mm.eval(procDef)
    return procName