0

rvui.minorModeFromName in python

1. Is it possible to access existing minorMode's from python? I would like to trigger the ShotgunMinorMode.swapMedia function from a python interface I'm developing. I will also probably want to access other methods on that class as well.

I've tried various attempts at rv.runtime.eval, so far none have worked, and often they cause rv to crash. Its possible I don't know exactly how to build the command to pass in.

I haven't been able to use pymu.MuSymbol to access the MinorMode. `MuSymbol('shotgun_mode.theMode')()` returns a dict of strings and booleans, nothing I can call. `sg = MuSymbol('shotgun_mode.theMode().swapMedia')` This causes `Exception: Could not find Mu symbol 'shotgun_mode.theMode().swapMedia'`

So far, the only thing I've gotten to work is to modify shotgun_mode.mu to include a external function.

```
\: swapMedia (void; string allOrOne, string media)
{
    ShotgunMinorMode m = theMode();
    Event ev;
    m.swapMedia(allOrOne, media, ev);
}
```
I can then use MuSymbol to swap the media.
```
sm = MuSymbol('shotgun_mode.swapMedia')
sm('all', 'Movie')
sm('all', 'Frames')
```

Modifying shotgun_mode.mu is something I would prefer to avoid. And I would also like to avoid having to define a special function for every function I would like to call.

2. I'm modifying shotgun_mode.mu because I'm not sure how to include a custom mu module in my own rvpkg file that is using python modes. Is it possible to include both .py and .mu modes in a rvpkg and have their load set to immediate? I got this error when I added new_mode to the PACKAGE file

```
ImportError: No module named new_mode
ERROR: python module new_mode could not be imported
```

6 comments

  • 0
    Avatar
    Jon Morley

    Hi Mike,

    The problem with using the MuSymbol approach (without making that external call) is that you need live access to the particular instance of the mode that has been loaded by the mode manager. As you found that level of language translateability is not supported. You simply get back an uncallable dictionary representing parts of the Mu mode. Therefore the only way to achieve what you are after without extending the existing package is through rv.runtime.eval. I believe something like the following should work:

    ```
        mu = """
        {
            try
            {
                require shotgun_mode;
                shotgun_mode.theMode().swapMedia(allOrOne, media, nil);
             }
             catch (...)
             {
                 print("failed to swap media\n");
             }
         }
        """
        rv.runtime.eval (mu, ["commands", "rvtypes", "mode_manager"])
    ```

    Obviously you will still need to properly set allOrOne and media in your usage. Please tell me if that works for you.

    Thanks,
    Jon

  • 0
    Avatar
    Jon Morley

    (I am having trouble formatting the code in here. I tried to use backticks to format that code but it didn't seem to matter. You can ignore the first and last triple backtick sets.)

  • 0
    Avatar
    Mike Hendricks

    Yep its working. However the try/catch didn't seem to catch anything. Python just raised a exception, which I would prefer that it does anyway. 

        def shotgun_mode(function, *args):
            arguments = []
            for arg in args:
                if arg is None:
                    arguments.append('nil')
                elif isinstance(arg, basestring):
                    arguments.append('"{}"'.format(arg))
                else:
                    arguments.append(str(arg))
            arguments = ', '.join(arguments)
            mu = r"""
            {{
                require shotgun_mode;
                shotgun_mode.theMode().{function}({args});
            }}
            """.format(function=function, args=arguments)
            return rv.runtime.eval (mu, ["commands", "rvtypes", "mode_manager"])

    I created a function that allows you to call any of the methods on shotgun_mode with various args and return the results. Though the arg parsing may need some extra work for types other than string and nil. 

        >>> print shotgun_mode('swapMedia', 'all', 'Movie', None)

        void

        >>> print shotgun_mode('swapMedia', 'all', 'Frames', None)

        void

        >>> print shotgun_mode('singleSourceName')

        "sourceGroup000000_source"

    The other reason I removed the try/catch was because I would like to be able to get the result of the function. I'm not sure how to capture a return value to a variable. I tried `let myVar = shotgun_mode.theMode().{function}({args});`, and that worked except for if a function had a return type of void. Also I was unsure of how to return that variable at the end. I guess might have to define a work function and call it as the last line of the expression.

    For now, this works for me. Its definitely possible to crash RV if you pass the wrong commands to rv.runtime.eval, but once you have something that works its pretty stable.

  • 0
    Avatar
    Mike Hendricks

    Oh, and Jon, Dan Akers says hi.

  • 0
    Avatar
    Jon Morley

    Hi Mike,

    That's awesome work, man! I am not sure if there is a way to generalize for the void return. Perhaps that is a good time to use the try/catch.

    Tell Dan HI!!! From me and Tannaz! I miss the hell out him.

    Thanks,
    Jon

  • 0
    Avatar
    Jon Morley

    Oh! One other thing, Mike. We are working to update our shotgun integration to use Shotgun ToolKit in place of the Mu stuff. When that comes around this will all be a thing of the past. #fingerscrossed #famouslastwords

Please sign in to leave a comment.