Friday, October 26, 2012

How do you find where a python attribute "comes from"?

I work on a python project in the visual-effects industry called pymel, and someone recently asked me about the 'vtx' "attribute" on a mesh object - where it came from, and how they would find that out.  The answer is that it's added using the __getattr__ method on the Mesh class... but this got me thinking - is there a general way to find where a given attribute "comes from?"

When classes use tricks like __getattr__, it's hard to determine - standard methods like using dir or searching through the mro's __dict__ entries won't help.

The only way I could think of to find out it's from a __getattr__ would be to march up the mro chain, looking for __getattrs__, and testing them - to see if they return a result for the desired attribute, and at what point that result changes.

So, I wrote a function which does just that... and while it's at it, also checks the __dict__, __slots__, and __getattribute__.  It even does a last-ditch check to see if it's a c-compiled object. It's designed to generally tell you, "where the heck did this attribute come from"?
In order to get all (or at least, most) of the edge cases right, it ended up being way more complex than I'd originally imagined.. but it seems to get things right nearly all of the time. Hopefully it helps someone!

Thursday, July 9, 2009

Getting the type of OS

Just something that came up recently - how to use python to find what OS the user is running.

If you only need the general "type" of os (ie, Windows, Mac OSX, Linux), I've found the best solution is to use os.name first, as it's result is guaranteed to be one of only a few values, and then platform.system() to get finer grained results (ie, differentiate between OSX and *nix).

The problem with just using platform.system() is that it's return value isn't "guaranteed" be one of a few values, as the Python community learned when Vista was released. Whereas previous versions of Windows would return "Windows", Vista returns "Microsoft". While this may be considered a bug, it taught me that it's probably safest to just use os.name when possible, and only resort to other methods when this doesn't provide enough information.

Unfortunately, this is the case when trying to differentiate OSX and Unix/Linux - os.name returns 'posix' for both. So there, we resort to platform.system(), which will return 'Darwin' or 'Linux'.

Of course, you may need more fine-grained information, and there's other functions that can help with that - platform.uname(), platform.system_alias(), platform.uname(), maya.cmds.about() if Maya is initialized, etc.

Wednesday, July 8, 2009

Mirorring blendshapes, and downloading scripts

So I needed to mirror a blendshape again, and didn't want to do it manually, so (as usual) my first impulse was to write a script to do it... but this time, I actually did the smart thing, and just checked highend3d for one.

I found a bunch, of course. And settled on this one - ntMirrorBlendShape by Nelson Teixeira - solely because it had the most downloads. It does exactly what I needed, though, so thanks Nelson!

However, my pull to write my own solution - even in cases such as this where the smarter option is clearly to use existing code - never seems to go away. For instance, I inevitably find myself wanting features not already present - in this case, topological symmetry, ala that in Mudbox / Silo / Zbrush. (And, in this case, it wouldn't be that hard to implement, since I've already written code that does the hard part - topological matching of two non-mirrored meshes - that I originally wrote to fix cases where vert order somehow got messed up. Adapting it for use with symmetry should be pretty simple...) Or mirroring across axes other than X. Never mind that I don't actually NEED those features to solve my initial problem... the itch persists.

For now, I've been able to remind myself that time is of the essence - I really need to finish up my demo reel - but I know the problem will pop up again at some point. Do you think anyone makes some sort of soothing spray for Scripter's Itch?

So I decided to finally start a blog...

...and here it is. Tada!

I'll mostly be musing about stuff related to 3D graphics - and particularly rigging and scripting, since that's what I'm specializing in - but no promises that it won't wander into other, random topics (such as: http://www.fupenguin.com/).