Problem with Pymel class inheritance

Hi all, sorry if this has been asked before…

I’m having an issue trying to inherit from a pymel node type. I’m getting this error in Maya 2015:

// Error: Determined type is Joint, which is not a subclass of desired type LegJoint
# Traceback (most recent call last):
#   File "<maya console>", line 69, in <module>
#   File "C:\Program Files\Autodesk\Maya2015\Python\lib\site-packages\pymel\core\general.py", line 2158, in __new__
#     return cls(newNode)
#   File "C:\Program Files\Autodesk\Maya2015\Python\lib\site-packages\pymel\core\general.py", line 2178, in __new__
#     raise TypeError, "Determined type is %s, which is not a subclass of desired type %s" % ( pymelType.__name__, cls.__name__ )
# TypeError: Determined type is Joint, which is not a subclass of desired type LegJoint //

I’ve even tried following the example given here to no avail:

Has anybody experienced this error before?

I would wager that LegJoint is a subclass of Joint, and you’re trying to make a subclass of LegJoint, but somehow Joint is getting passed in instead. It’s hard to know just looking at the callstack.

I’m not seeing any problems with the system. Does the following not work for you?


import maya.OpenMaya as om
import pymel.core as pm
from pymel.internal import factories

class ExportJoint(pm.nt.Joint):

    @classmethod
    def _isVirtual(cls, obj, name):
        return om.MFnDependencyNode(obj).hasAttribute(u'export_joint')

    def do_thing(self):
        print(self)
        
factories.virtualClasses.register(ExportJoint, nameRequired=False)

# Make a test joint with our attribute on it.
test = pm.joint()
test.addAttr(u'export_joint', attributeType='message')

# Add another joint that is well just joint
test2 = pm.joint()
# Find all joints with our attribute
tst = pm.ls('*.export_joint', o=True)

# We really only want one joint to have been found
if len(tst) == 1:
    # Check that pymel returned our virtual class
    print(tst[0].__class__ is ExportJoint)


R.White,
That runs just fine for me, however, as soon as I try to create a new object of type ExportJoint, the error appears.

testObj = ExportJoint()

Instead of adding the class as an attribute as per your example, I’d like to be able to create new objects like this. Maybe I’m miss understanding the use of virtual classes?

Ah there we go. I got the same error. I think I’ve never had that happen because I’ve always used the virtual classes as wrappers, and never created nodes from them directly.

So my guess is that because ExportJoint requires that the ‘export_joint’ attribute exists, and creating a new joint wouldn’t have that attribute yet.

The pymel example gets around this using the _postCreateVirtual method. So that when creating a new node it can assign the needed attributes at instantiation.

I updated my example to use the _postCreateVirtual method setup.


import maya.OpenMaya as om
import pymel.core as pm
from pymel.internal import factories

class ExportJoint(pm.nt.Joint):
    
    _export_joint = True
    @classmethod
    def _isVirtual(cls, obj, name):
        return getattr(cls, '_export_joint', om.MFnDependencyNode(obj).hasAttribute(u'export_joint'))

    def do_thing(self):
        print(self)
        
    @classmethod
    def _postCreateVirtual(cls, new_node, **kwargs ):
        # add the identifying attribute. the attribute name will be set on subclasses of this class
        new_node.addAttr(u'export_joint', attributeType='message')

                
factories.virtualClasses.register(ExportJoint, nameRequired=False)

# Make a test joint with our attribute on it.
test = pm.joint()
test.addAttr(u'export_joint', attributeType='message')

# Add another joint that is well just joint
test2 = pm.joint()
# Find all joints with our attribute
tst = pm.ls('*.export_joint', o=True)

# We really only want one joint to have been found
if len(tst) == 1:
    # Check that pymel returned our virtual class
    print(tst[0].__class__ is ExportJoint)
    
ex = ExportJoint()

print(ex.export_joint)

Thats the one! Thanks a bunch, its working great for me now.

Awesome, glad to help.