def _plug_to_python(plug, unit=None, context=None):
    'Convert native `plug` to Python type\n\n    Arguments:\n        plug (om.MPlug): Native Maya plug\n        unit (int, optional): Return value in this unit, e.g. Meters\n        context (om.MDGContext, optional): Return value in this context\n\n    '
    assert (not plug.isNull), ("'%s' was null" % plug)
    kwargs = dict()
    if (context is not None):
        kwargs['context'] = context
    if (plug.isArray and plug.isCompound):
        return _plug_to_python(plug.elementByLogicalIndex(0), unit, context)
    elif plug.isArray:
        return tuple((_plug_to_python(plug.elementByLogicalIndex(index), unit, context) for index in range(plug.evaluateNumElements())))
    elif plug.isCompound:
        return tuple((_plug_to_python(plug.child(index), unit, context) for index in range(plug.numChildren())))
    attr = plug.attribute()
    type = attr.apiType()
    if (type == om.MFn.kTypedAttribute):
        innerType = om.MFnTypedAttribute(attr).attrType()
        if (innerType == om.MFnData.kAny):
            return None
        elif (innerType == om.MFnData.kMatrix):
            if plug.isArray:
                plug = plug.elementByLogicalIndex(0)
            return tuple(om.MFnMatrixData(plug.asMObject(**kwargs)).matrix())
        elif (innerType == om.MFnData.kString):
            return plug.asString(**kwargs)
        elif (innerType == om.MFnData.kNurbsCurve):
            return om.MFnNurbsCurveData(plug.asMObject(**kwargs))
        elif (innerType == om.MFnData.kComponentList):
            return None
        elif (innerType == om.MFnData.kInvalid):
            return None
        else:
            log.debug(('Unsupported kTypedAttribute: %s' % innerType))
            return None
    elif (type == om.MFn.kMatrixAttribute):
        return tuple(om.MFnMatrixData(plug.asMObject(**kwargs)).matrix())
    elif (type == om.MFnData.kDoubleArray):
        raise TypeError(('%s: kDoubleArray is not supported' % plug))
    elif (type in (om.MFn.kDoubleLinearAttribute, om.MFn.kFloatLinearAttribute)):
        if (unit is None):
            return plug.asMDistance(**kwargs).asUnits(Centimeters)
        elif (unit == Millimeters):
            return plug.asMDistance(**kwargs).asMillimeters()
        elif (unit == Centimeters):
            return plug.asMDistance(**kwargs).asCentimeters()
        elif (unit == Meters):
            return plug.asMDistance(**kwargs).asMeters()
        elif (unit == Kilometers):
            return plug.asMDistance(**kwargs).asKilometers()
        elif (unit == Inches):
            return plug.asMDistance(**kwargs).asInches()
        elif (unit == Feet):
            return plug.asMDistance(**kwargs).asFeet()
        elif (unit == Miles):
            return plug.asMDistance(**kwargs).asMiles()
        elif (unit == Yards):
            return plug.asMDistance(**kwargs).asYards()
        else:
            raise TypeError(("Unsupported unit '%d'" % unit))
    elif (type in (om.MFn.kDoubleAngleAttribute, om.MFn.kFloatAngleAttribute)):
        if (unit is None):
            return plug.asMAngle(**kwargs).asUnits(Radians)
        elif (unit == Degrees):
            return plug.asMAngle(**kwargs).asDegrees()
        elif (unit == Radians):
            return plug.asMAngle(**kwargs).asRadians()
        elif (unit == AngularSeconds):
            return plug.asMAngle(**kwargs).asAngSeconds()
        elif (unit == AngularMinutes):
            return plug.asMAngle(**kwargs).asAngMinutes()
        else:
            raise TypeError(("Unsupported unit '%d'" % unit))
    elif (type == om.MFn.kNumericAttribute):
        innerType = om.MFnNumericAttribute(attr).numericType()
        if (innerType == om.MFnNumericData.kBoolean):
            return plug.asBool(**kwargs)
        elif (innerType in (om.MFnNumericData.kShort, om.MFnNumericData.kInt, om.MFnNumericData.kLong, om.MFnNumericData.kByte)):
            return plug.asInt(**kwargs)
        elif (innerType in (om.MFnNumericData.kFloat, om.MFnNumericData.kDouble, om.MFnNumericData.kAddr)):
            return plug.asDouble(**kwargs)
        else:
            raise TypeError(('Unsupported numeric type: %s' % innerType))
    elif (type == om.MFn.kEnumAttribute):
        return plug.asShort(**kwargs)
    elif (type == om.MFn.kMessageAttribute):
        return True
    elif (type == om.MFn.kTimeAttribute):
        if unit:
            return plug.asMTime(**kwargs).asUnits(unit)
        else:
            return plug.asMTime(**kwargs).value
    elif (type == om.MFn.kInvalid):
        raise TypeError(('%s was invalid' % plug.name()))
    else:
        raise TypeError(("Unsupported type '%s'" % type))
Convert native `plug` to Python type

Arguments:
    plug (om.MPlug): Native Maya plug
    unit (int, optional): Return value in this unit, e.g. Meters
    context (om.MDGContext, optional): Return value in this context
def _plug_to_python(plug, unit=None, context=None):
    'Convert native `plug` to Python type\n\n    Arguments:\n        plug (om.MPlug): Native Maya plug\n        unit (int, optional): Return value in this unit, e.g. Meters\n        context (om.MDGContext, optional): Return value in this context\n\n    '
    assert (not plug.isNull), ("'%s' was null" % plug)
    kwargs = dict()
    if (context is not None):
        kwargs['context'] = context
    if (plug.isArray and plug.isCompound):
        return _plug_to_python(plug.elementByLogicalIndex(0), unit, context)
    elif plug.isArray:
        return tuple((_plug_to_python(plug.elementByLogicalIndex(index), unit, context) for index in range(plug.evaluateNumElements())))
    elif plug.isCompound:
        return tuple((_plug_to_python(plug.child(index), unit, context) for index in range(plug.numChildren())))
    attr = plug.attribute()
    type = attr.apiType()
    if (type == om.MFn.kTypedAttribute):
        innerType = om.MFnTypedAttribute(attr).attrType()
        if (innerType == om.MFnData.kAny):
            return None
        elif (innerType == om.MFnData.kMatrix):
            if plug.isArray:
                plug = plug.elementByLogicalIndex(0)
            return tuple(om.MFnMatrixData(plug.asMObject(**kwargs)).matrix())
        elif (innerType == om.MFnData.kString):
            return plug.asString(**kwargs)
        elif (innerType == om.MFnData.kNurbsCurve):
            return om.MFnNurbsCurveData(plug.asMObject(**kwargs))
        elif (innerType == om.MFnData.kComponentList):
            return None
        elif (innerType == om.MFnData.kInvalid):
            return None
        else:
            log.debug(('Unsupported kTypedAttribute: %s' % innerType))
            return None
    elif (type == om.MFn.kMatrixAttribute):
        return tuple(om.MFnMatrixData(plug.asMObject(**kwargs)).matrix())
    elif (type == om.MFnData.kDoubleArray):
        raise TypeError(('%s: kDoubleArray is not supported' % plug))
    elif (type in (om.MFn.kDoubleLinearAttribute, om.MFn.kFloatLinearAttribute)):
        if (unit is None):
            return plug.asMDistance(**kwargs).asUnits(Centimeters)
        elif (unit == Millimeters):
            return plug.asMDistance(**kwargs).asMillimeters()
        elif (unit == Centimeters):
            return plug.asMDistance(**kwargs).asCentimeters()
        elif (unit == Meters):
            return plug.asMDistance(**kwargs).asMeters()
        elif (unit == Kilometers):
            return plug.asMDistance(**kwargs).asKilometers()
        elif (unit == Inches):
            return plug.asMDistance(**kwargs).asInches()
        elif (unit == Feet):
            return plug.asMDistance(**kwargs).asFeet()
        elif (unit == Miles):
            return plug.asMDistance(**kwargs).asMiles()
        elif (unit == Yards):
            return plug.asMDistance(**kwargs).asYards()
        else:
            raise TypeError(("Unsupported unit '%d'" % unit))
    elif (type in (om.MFn.kDoubleAngleAttribute, om.MFn.kFloatAngleAttribute)):
        if (unit is None):
            return plug.asMAngle(**kwargs).asUnits(Radians)
        elif (unit == Degrees):
            return plug.asMAngle(**kwargs).asDegrees()
        elif (unit == Radians):
            return plug.asMAngle(**kwargs).asRadians()
        elif (unit == AngularSeconds):
            return plug.asMAngle(**kwargs).asAngSeconds()
        elif (unit == AngularMinutes):
            return plug.asMAngle(**kwargs).asAngMinutes()
        else:
            raise TypeError(("Unsupported unit '%d'" % unit))
    elif (type == om.MFn.kNumericAttribute):
        innerType = om.MFnNumericAttribute(attr).numericType()
        if (innerType == om.MFnNumericData.kBoolean):
            return plug.asBool(**kwargs)
        elif (innerType in (om.MFnNumericData.kShort, om.MFnNumericData.kInt, om.MFnNumericData.kLong, om.MFnNumericData.kByte)):
            return plug.asInt(**kwargs)
        elif (innerType in (om.MFnNumericData.kFloat, om.MFnNumericData.kDouble, om.MFnNumericData.kAddr)):
            return plug.asDouble(**kwargs)
        else:
            raise TypeError(('Unsupported numeric type: %s' % innerType))
    elif (type == om.MFn.kEnumAttribute):
        return plug.asShort(**kwargs)
    elif (type == om.MFn.kMessageAttribute):
        return True
    elif (type == om.MFn.kTimeAttribute):
        if unit:
            return plug.asMTime(**kwargs).asUnits(unit)
        else:
            return plug.asMTime(**kwargs).value
    elif (type == om.MFn.kInvalid):
        raise TypeError(('%s was invalid' % plug.name()))
    else:
        raise TypeError(("Unsupported type '%s'" % type))