DocumentObject::~DocumentObject(void)
{
    if (!PythonObject.is(Py::_None())){
        // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed
        // Python object or not. In the constructor we forced the wrapper to own the object so we need
        // not to dec'ref the Python object any more.
        // But we must still invalidate the Python object because it need not to be
        // destructed right now because the interpreter can own several references to it.
        Base::PyObjectBase* obj = (Base::PyObjectBase*)PythonObject.ptr();
        // Call before decrementing the reference counter, otherwise a heap error can occur
        obj->setInvalid();
    }
}
PyObject *PropertyPartShape::getPyObject(void)
{
    Base::PyObjectBase* prop;
    const TopoDS_Shape& sh = _Shape._Shape;
    if (sh.IsNull()) {
        prop = new TopoShapePy(new TopoShape(sh));
    }
    else {
        TopAbs_ShapeEnum type = sh.ShapeType();
        switch (type)
        {
        case TopAbs_COMPOUND:
            prop = new TopoShapeCompoundPy(new TopoShape(sh));
            break;
        case TopAbs_COMPSOLID:
            prop = new TopoShapeCompSolidPy(new TopoShape(sh));
            break;
        case TopAbs_SOLID:
            prop = new TopoShapeSolidPy(new TopoShape(sh));
            break;
        case TopAbs_SHELL:
            prop = new TopoShapeShellPy(new TopoShape(sh));
            break;
        case TopAbs_FACE:
            prop = new TopoShapeFacePy(new TopoShape(sh));
            break;
        case TopAbs_WIRE:
            prop = new TopoShapeWirePy(new TopoShape(sh));
            break;
        case TopAbs_EDGE:
            prop = new TopoShapeEdgePy(new TopoShape(sh));
            break;
        case TopAbs_VERTEX:
            prop = new TopoShapeVertexPy(new TopoShape(sh));
            break;
        case TopAbs_SHAPE:
        default:
            prop = new TopoShapePy(new TopoShape(sh));
            break;
        }
    }

    if (prop) prop->setConst();
    return prop;
}
Example #3
0
PyObject* Application::sListDocuments(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
{
    if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C
        return NULL;                       // NULL triggers exception
    PY_TRY {
        PyObject *pDict = PyDict_New();
        PyObject *pKey;
        Base::PyObjectBase* pValue;

        for (std::map<std::string,Document*>::const_iterator It = GetApplication().DocMap.begin();
             It != GetApplication().DocMap.end();++It) {
            pKey   = PyString_FromString(It->first.c_str());
            // GetPyObject() increments
            pValue = static_cast<Base::PyObjectBase*>(It->second->getPyObject());
            PyDict_SetItem(pDict, pKey, pValue);
            // now we can decrement again as PyDict_SetItem also has incremented
            pValue->DecRef();
        }

        return pDict;
    } PY_CATCH;
}
Example #4
0
QMap<QString, CallTip> CallTipsList::extractTips(const QString& context) const
{
    Base::PyGILStateLocker lock;
    QMap<QString, CallTip> tips;
    if (context.isEmpty())
        return tips;

    try {
        Py::Module module("__main__");
        Py::Dict dict = module.getDict();
#if 0
        QStringList items = context.split(QLatin1Char('.'));
        QString modname = items.front();
        items.pop_front();
        if (!dict.hasKey(std::string(modname.toLatin1())))
            return tips; // unknown object

        // get the Python object we need
        Py::Object obj = dict.getItem(std::string(modname.toLatin1()));
        while (!items.isEmpty()) {
            QByteArray name = items.front().toLatin1();
            std::string attr = name.constData();
            items.pop_front();
            if (obj.hasAttr(attr))
                obj = obj.getAttr(attr);
            else
                return tips;
        }
#else
        // Don't use hasattr & getattr because if a property is bound to a method this will be executed twice.
        PyObject* code = Py_CompileString(static_cast<const char*>(context.toLatin1()), "<CallTipsList>", Py_eval_input);
        if (!code) {
            PyErr_Clear();
            return tips;
        }

        PyObject* eval = 0;
        if (PyCode_Check(code)) {
            eval = PyEval_EvalCode(reinterpret_cast<PyCodeObject*>(code), dict.ptr(), dict.ptr());
        }
        Py_DECREF(code);
        if (!eval) {
            PyErr_Clear();
            return tips;
        }
        Py::Object obj(eval, true);
#endif

        // Checks whether the type is a subclass of PyObjectBase because to get the doc string
        // of a member we must get it by its type instead of its instance otherwise we get the
        // wrong string, namely that of the type of the member. 
        // Note: 3rd party libraries may use their own type object classes so that we cannot 
        // reliably use Py::Type. To be on the safe side we should use Py::Object to assign
        // the used type object to.
        //Py::Object type = obj.type();
        Py::Object type(PyObject_Type(obj.ptr()), true);
        Py::Object inst = obj; // the object instance 
        union PyType_Object typeobj = {&Base::PyObjectBase::Type};
        union PyType_Object typedoc = {&App::DocumentObjectPy::Type};
        union PyType_Object basetype = {&PyBaseObject_Type};

        if (PyObject_IsSubclass(type.ptr(), typedoc.o) == 1) {
            // From the template Python object we don't query its type object because there we keep
            // a list of additional methods that we won't see otherwise. But to get the correct doc
            // strings we query the type's dict in the class itself.
            // To see if we have a template Python object we check for the existence of supportedProperties
            if (!type.hasAttr("supportedProperties")) {
                obj = type;
            }
        }
        else if (PyObject_IsSubclass(type.ptr(), typeobj.o) == 1) {
            obj = type;
        }
        else if (PyInstance_Check(obj.ptr())) {
            // instances of old style classes
            PyInstanceObject* inst = reinterpret_cast<PyInstanceObject*>(obj.ptr());
            PyObject* classobj = reinterpret_cast<PyObject*>(inst->in_class);
            obj = Py::Object(classobj);
        }
        else if (PyObject_IsInstance(obj.ptr(), basetype.o) == 1) {
            // New style class which can be a module, type, list, tuple, int, float, ...
            // Make sure it's not a type objec
            union PyType_Object typetype = {&PyType_Type};
            if (PyObject_IsInstance(obj.ptr(), typetype.o) != 1) {
                // this should be now a user-defined Python class
                // http://stackoverflow.com/questions/12233103/in-python-at-runtime-determine-if-an-object-is-a-class-old-and-new-type-instan
                if (Py_TYPE(obj.ptr())->tp_flags & Py_TPFLAGS_HEAPTYPE) {
                    obj = type;
                }
            }
        }

        // If we have an instance of PyObjectBase then determine whether it's valid or not
        if (PyObject_IsInstance(inst.ptr(), typeobj.o) == 1) {
            Base::PyObjectBase* baseobj = static_cast<Base::PyObjectBase*>(inst.ptr());
            const_cast<CallTipsList*>(this)->validObject = baseobj->isValid();
        }
        else {
            // PyObject_IsInstance might set an exception
            PyErr_Clear();
        }

        Py::List list(obj.dir());

        // If we derive from PropertyContainerPy we can search for the properties in the
        // C++ twin class.
        union PyType_Object proptypeobj = {&App::PropertyContainerPy::Type};
        if (PyObject_IsSubclass(type.ptr(), proptypeobj.o) == 1) {
            // These are the attributes of the instance itself which are NOT accessible by
            // its type object
            extractTipsFromProperties(inst, tips);
        }

        // If we derive from App::DocumentPy we have direct access to the objects by their internal
        // names. So, we add these names to the list, too.
        union PyType_Object appdoctypeobj = {&App::DocumentPy::Type};
        if (PyObject_IsSubclass(type.ptr(), appdoctypeobj.o) == 1) {
            App::DocumentPy* docpy = (App::DocumentPy*)(inst.ptr());
            App::Document* document = docpy->getDocumentPtr();
            // Make sure that the C++ object is alive
            if (document) {
                std::vector<App::DocumentObject*> objects = document->getObjects();
                Py::List list;
                for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it)
                    list.append(Py::String((*it)->getNameInDocument()));
                extractTipsFromObject(inst, list, tips);
            }
        }

        // If we derive from Gui::DocumentPy we have direct access to the objects by their internal
        // names. So, we add these names to the list, too.
        union PyType_Object guidoctypeobj = {&Gui::DocumentPy::Type};
        if (PyObject_IsSubclass(type.ptr(), guidoctypeobj.o) == 1) {
            Gui::DocumentPy* docpy = (Gui::DocumentPy*)(inst.ptr());
            if (docpy->getDocumentPtr()) {
                App::Document* document = docpy->getDocumentPtr()->getDocument();
                // Make sure that the C++ object is alive
                if (document) {
                    std::vector<App::DocumentObject*> objects = document->getObjects();
                    Py::List list;
                    for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it)
                        list.append(Py::String((*it)->getNameInDocument()));
                    extractTipsFromObject(inst, list, tips);
                }
            }
        }

        // These are the attributes from the type object
        extractTipsFromObject(obj, list, tips);
    }
    catch (Py::Exception& e) {
        // Just clear the Python exception
        e.clear();
    }

    return tips;
}
Py::Object TopoShapeFacePy::getSurface() const
{
    const TopoDS_Face& f = TopoDS::Face(getTopoShapePtr()->getShape());
    BRepAdaptor_Surface adapt(f);
    Base::PyObjectBase* surface = 0;
    switch(adapt.GetType())
    {
    case GeomAbs_Plane:
        {
            GeomPlane* plane = new GeomPlane();
            Handle(Geom_Plane) this_surf = Handle(Geom_Plane)::DownCast
                (plane->handle());
            this_surf->SetPln(adapt.Plane());
            surface = new PlanePy(plane);
            break;
        }
    case GeomAbs_Cylinder:
        {
            GeomCylinder* cylinder = new GeomCylinder();
            Handle(Geom_CylindricalSurface) this_surf = Handle(Geom_CylindricalSurface)::DownCast
                (cylinder->handle());
            this_surf->SetCylinder(adapt.Cylinder());
            surface = new CylinderPy(cylinder);
            break;
        }
    case GeomAbs_Cone:
        {
            GeomCone* cone = new GeomCone();
            Handle(Geom_ConicalSurface) this_surf = Handle(Geom_ConicalSurface)::DownCast
                (cone->handle());
            this_surf->SetCone(adapt.Cone());
            surface = new ConePy(cone);
            break;
        }
    case GeomAbs_Sphere:
        {
            GeomSphere* sphere = new GeomSphere();
            Handle(Geom_SphericalSurface) this_surf = Handle(Geom_SphericalSurface)::DownCast
                (sphere->handle());
            this_surf->SetSphere(adapt.Sphere());
            surface = new SpherePy(sphere);
            break;
        }
    case GeomAbs_Torus:
        {
            GeomToroid* toroid = new GeomToroid();
            Handle(Geom_ToroidalSurface) this_surf = Handle(Geom_ToroidalSurface)::DownCast
                (toroid->handle());
            this_surf->SetTorus(adapt.Torus());
            surface = new ToroidPy(toroid);
            break;
        }
    case GeomAbs_BezierSurface:
        {
            GeomBezierSurface* surf = new GeomBezierSurface(adapt.Bezier());
            surface = new BezierSurfacePy(surf);
            break;
        }
    case GeomAbs_BSplineSurface:
        {
            GeomBSplineSurface* surf = new GeomBSplineSurface(adapt.BSpline());
            surface = new BSplineSurfacePy(surf);
            break;
        }
    case GeomAbs_SurfaceOfRevolution:
        {
            Handle(Geom_Surface) s = BRep_Tool::Surface(f);
            Handle(Geom_SurfaceOfRevolution) rev = Handle(Geom_SurfaceOfRevolution)::DownCast(s);
            if (rev.IsNull()) {
                Handle(Geom_RectangularTrimmedSurface) rect = Handle(Geom_RectangularTrimmedSurface)::DownCast(s);
                rev = Handle(Geom_SurfaceOfRevolution)::DownCast(rect->BasisSurface());
            }
            if (!rev.IsNull()) {
                GeomSurfaceOfRevolution* surf = new GeomSurfaceOfRevolution(rev);
                surface = new SurfaceOfRevolutionPy(surf);
                break;
            }
            else {
                throw Py::RuntimeError("Failed to convert to surface of revolution");
            }
        }
    case GeomAbs_SurfaceOfExtrusion:
        {
            Handle(Geom_Surface) s = BRep_Tool::Surface(f);
            Handle(Geom_SurfaceOfLinearExtrusion) ext = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(s);
            if (ext.IsNull()) {
                Handle(Geom_RectangularTrimmedSurface) rect = Handle(Geom_RectangularTrimmedSurface)::DownCast(s);
                ext = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(rect->BasisSurface());
            }
            if (!ext.IsNull()) {
                GeomSurfaceOfExtrusion* surf = new GeomSurfaceOfExtrusion(ext);
                surface = new SurfaceOfExtrusionPy(surf);
                break;
            }
            else {
                throw Py::RuntimeError("Failed to convert to surface of extrusion");
            }
        }
    case GeomAbs_OffsetSurface:
        {
            Handle(Geom_Surface) s = BRep_Tool::Surface(f);
            Handle(Geom_OffsetSurface) off = Handle(Geom_OffsetSurface)::DownCast(s);
            if (off.IsNull()) {
                Handle(Geom_RectangularTrimmedSurface) rect = Handle(Geom_RectangularTrimmedSurface)::DownCast(s);
                off = Handle(Geom_OffsetSurface)::DownCast(rect->BasisSurface());
            }
            if (!off.IsNull()) {
                GeomOffsetSurface* surf = new GeomOffsetSurface(off);
                surface = new OffsetSurfacePy(surf);
                break;
            }
            else {
                throw Py::RuntimeError("Failed to convert to offset surface");
            }
        }
    case GeomAbs_OtherSurface:
        break;
    }

    if (surface) {
        surface->setNotTracking();
        return Py::asObject(surface);
    }

    throw Py::TypeError("undefined surface type");
}
Example #6
0
QMap<QString, CallTip> CallTipsList::extractTips(const QString& context) const
{
    Base::PyGILStateLocker lock;
    QMap<QString, CallTip> tips;
    if (context.isEmpty())
        return tips;

    try {
        QStringList items = context.split(QLatin1Char('.'));
        Py::Module module("__main__");
        Py::Dict dict = module.getDict();
        QString modname = items.front();
        items.pop_front();
        if (!dict.hasKey(std::string(modname.toAscii())))
            return tips; // unknown object

        // get the Python object we need
        Py::Object obj = dict.getItem(std::string(modname.toAscii()));
        while (!items.isEmpty()) {
            QByteArray name = items.front().toAscii();
            std::string attr = name.constData();
            items.pop_front();
            if (obj.hasAttr(attr))
                obj = obj.getAttr(attr);
            else
                return tips;
        }
        
        // Checks whether the type is a subclass of PyObjectBase because to get the doc string
        // of a member we must get it by its type instead of its instance otherwise we get the
        // wrong string, namely that of the type of the member. 
        // Note: 3rd party libraries may use their own type object classes so that we cannot 
        // reliably use Py::Type. To be on the safe side we should use Py::Object to assign
        // the used type object to.
        //Py::Object type = obj.type();
        Py::Object type(PyObject_Type(obj.ptr()), true);
        Py::Object inst = obj; // the object instance 
        union PyType_Object typeobj = {&Base::PyObjectBase::Type};
        union PyType_Object typedoc = {&App::DocumentObjectPy::Type};
        if (PyObject_IsSubclass(type.ptr(), typedoc.o) == 1) {
            // From the template Python object we don't query its type object because there we keep
            // a list of additional methods that we won't see otherwise. But to get the correct doc
            // strings we query the type's dict in the class itself.
            // To see if we have a template Python object we check for the existence of supportedProperties
            if (!type.hasAttr("supportedProperties")) {
                obj = type;
            }
        }
        else if (PyObject_IsSubclass(type.ptr(), typeobj.o) == 1) {
            obj = type;
        }
        
        // If we have an instance of PyObjectBase then determine whether it's valid or not
        if (PyObject_IsInstance(inst.ptr(), typeobj.o) == 1) {
            Base::PyObjectBase* baseobj = static_cast<Base::PyObjectBase*>(inst.ptr());
            const_cast<CallTipsList*>(this)->validObject = baseobj->isValid();
        }
        else {
            // PyObject_IsInstance might set an exception
            PyErr_Clear();
        }

        Py::List list(PyObject_Dir(obj.ptr()), true);

        // If we derive from PropertyContainerPy we can search for the properties in the
        // C++ twin class.
        union PyType_Object proptypeobj = {&App::PropertyContainerPy::Type};
        if (PyObject_IsSubclass(type.ptr(), proptypeobj.o) == 1) {
            // These are the attributes of the instance itself which are NOT accessible by
            // its type object
            extractTipsFromProperties(inst, tips);
        }

        // If we derive from App::DocumentPy we have direct access to the objects by their internal
        // names. So, we add these names to the list, too.
        union PyType_Object appdoctypeobj = {&App::DocumentPy::Type};
        if (PyObject_IsSubclass(type.ptr(), appdoctypeobj.o) == 1) {
            App::DocumentPy* docpy = (App::DocumentPy*)(inst.ptr());
            App::Document* document = docpy->getDocumentPtr();
            // Make sure that the C++ object is alive
            if (document) {
                std::vector<App::DocumentObject*> objects = document->getObjects();
                Py::List list;
                for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it)
                    list.append(Py::String((*it)->getNameInDocument()));
                extractTipsFromObject(inst, list, tips);
            }
        }

        // If we derive from Gui::DocumentPy we have direct access to the objects by their internal
        // names. So, we add these names to the list, too.
        union PyType_Object guidoctypeobj = {&Gui::DocumentPy::Type};
        if (PyObject_IsSubclass(type.ptr(), guidoctypeobj.o) == 1) {
            Gui::DocumentPy* docpy = (Gui::DocumentPy*)(inst.ptr());
            if (docpy->getDocumentPtr()) {
                App::Document* document = docpy->getDocumentPtr()->getDocument();
                // Make sure that the C++ object is alive
                if (document) {
                    std::vector<App::DocumentObject*> objects = document->getObjects();
                    Py::List list;
                    for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it)
                        list.append(Py::String((*it)->getNameInDocument()));
                    extractTipsFromObject(inst, list, tips);
                }
            }
        }

        // These are the attributes from the type object
        extractTipsFromObject(obj, list, tips);
    }
    catch (Py::Exception& e) {
        // Just clear the Python exception
        e.clear();
    }

    return tips;
}