Handling Legacy Tools in Maya 2017 / Pyside2

My week started with a fresh copy of Maya 2017 installed on my machine at work for me to evaluate. I’d been really impressed with the new Time Editor tool (which is excellent, by the way) as well as some of the performance increases with everyday features like the Graph Editor.

After a little bit of time spent reading the “What’s New” documentation I came across the news that PySide has been updated to PySide2 for Maya 2017, and with it much of the functionality enjoyed by users of Qt5.

The almost all of our tools use PySide on some level so I was keen to make sure everything was still working in 2017. I fired up our startup plugin which seeds our whole tool chain…

# Original exception was:# Traceback (most recent call last):
# File "<maya console>", line 2, in <module>
# ImportError: No module named PySide //
Uh oh

Ah, awkward. As PySide2 has been introduced, the original PySide library had been removed from the Maya 2017 site packages completely, leaving all of our tools a bit stranded and putting a sudden halt to our transition to Maya 2017.

# Common in all scripts
from PySide import QtCore, QtGui

# Or sometimes...
import PySide

The change from “PySide” to “PySide2” probably seems quite trivial, right? Wrong. Here’s why…

Early Proposed Solutions

  • Find / Replace “PySide” to “PySide2” in our entire tool repository
    - This would mean blindly updating more than 104 files, way too risky
    - In replacing all instances of PySide to the new library, I’d be breaking the tools for any legacy versions of Maya (2015, 2016) which we were likely to keep with for some time yet
  • Forcing PySide back into 2017
    - This would mean having major modifications to every user’s Program Files directory. This would be difficult to roll out.
    - Possible licensing issues.
  • Separate 2017 tools branch
    - I considered making a full copy of our tools repository purely for Maya 2017, culling any old unused scripts and porting the remaining ones over to PySide 2. Whilst this would be the cleanest port, it would mean having to maintain two versions of every frequently used script, which I’d rather not.

None of these methods were going to cut it. They were either too slow, too invasive or too difficult to maintain. We needed to get Maya 2017 up and running for the team as soon as possible and with all of 2016’s functionality in tact.

Requirements for the Solution

Preferably only affect as few files as possible

  • Not require any modifications to the user’s Maya install
  • Support both Maya 2016 (PySide) and Maya 2017 (PySide2) with the same script repository
  • Update completely silently with no loss of functionality to the user
  • Had to be working as soon as possible, we could not afford to spend weeks and weeks on a port

First Attempts

I started thinking about the common aspects of the two libraries and how I could start to simply point all my PySide references to PySide2. I’d need some sort of conditional import that would bring the correct library in depending on the presence of the PySide2 module.

This wasn’t perfect. I’d still need to add this to the top of every script and as I found out the name of the main library wasn’t the only thing that had changed. Many of the QWidget objects had been relocated to their own home in the PySide2.QWidgets module. A much nicer place for them, but all our old tools weren’t looking there!

So now I’ve got a new problem, not only do I have to get the PySide2 module re-pathed, but also anything that referenced the QtGui module (old home of QWidgets). I also need to make this change in a way that will propagate into all of our scripts from a single call at startup.

Conclusion

Watch out, it’s about to get a bit gross. To fix this I was going to have to get down into the sys.modules and tell Maya to relax, everything is exactly where it used to be, carry on as normal.

What follows is taken from a script that runs at Maya startup time and is propagated to all users when they start their machines. It is loaded before any of the other tools and as such is the perfect place to make these alterations to the modules.

I’ve explained what’s going on in the comments…

The final change in the script indicated to me that this probably wasn’t the last edge-case that I was going to have to address, but we were much further along than before.

At this point you could boot Maya and all of our tools were available in the menu and they functioned as expected, including custom widgets.

Did I hit any other snags?

Yes, the “setResizeMode()” for table header objects seemed to have been removed and there was no obvious replacement for it. Fortunately this method only occurred twice in our entire repository and on both occasions their usage was effectively redundant.

Is this a long term solution?

Goodness no, it’s a hack to get everything working. The advantage of this fix is that while it seems messy in this startup script, the way it presents to the rest of our tools is actually pretty simple and will allow our users and tool authors to carry on as usual without any major downtime. We can jump onto Maya 2017 and keep working immediately.

The Disadvantages of this Method

The biggest disadvantage of this method is that we won’t be able to start making use of the new features in PySide2 until we are confident that we’ll no longer need to straddle legacy platforms.

Eventually we’ll drop 2016 at which point we can do a cull of unused tools (see perhaps another article about logging Metrics) at which point we can begin a “clean” port of all our tools to PySide2.

Crisis adverted? For now.

Like what you read? Give Nick Rodgers a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.