FreeCAD

Форк
0
/
TypePyImp.cpp 
290 строк · 8.1 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 51 Franklin Street,      *
19
 *   Fifth Floor, Boston, MA  02110-1301, USA                              *
20
 *                                                                         *
21
 ***************************************************************************/
22

23

24
#include "PreCompiled.h"
25

26
#include "Type.h"
27
#include "BaseClassPy.h"
28
#include "BindingManager.h"
29
#include "TypePy.h"
30
#include "TypePy.cpp"
31

32
using namespace Base;
33

34
// returns a string which represent the object e.g. when printed in python
35
std::string TypePy::representation() const
36
{
37
    std::stringstream str;
38
    str << "<class '" << getBaseTypePtr()->getName() << "'>";
39
    return str.str();
40
}
41

42
PyObject* TypePy::fromName(PyObject* args)
43
{
44
    const char* name {};
45
    if (!PyArg_ParseTuple(args, "s", &name)) {
46
        return nullptr;
47
    }
48

49
    Base::Type type = Base::Type::fromName(name);
50
    return new TypePy(new Base::Type(type));
51
}
52

53
PyObject* TypePy::fromKey(PyObject* args)
54
{
55
    unsigned int index {};
56
    if (!PyArg_ParseTuple(args, "I", &index)) {
57
        return nullptr;
58
    }
59

60
    Base::Type type = Base::Type::fromKey(index);
61
    return new TypePy(new Base::Type(type));
62
}
63

64
PyObject* TypePy::getNumTypes(PyObject* args)
65
{
66
    if (!PyArg_ParseTuple(args, "")) {
67
        return nullptr;
68
    }
69

70
    int num = Base::Type::getNumTypes();
71
    return PyLong_FromLong(num);
72
}
73

74
PyObject* TypePy::getBadType(PyObject* args)
75
{
76
    if (!PyArg_ParseTuple(args, "")) {
77
        return nullptr;
78
    }
79

80
    Base::Type type = Base::Type::badType();
81
    return new TypePy(new Base::Type(type));
82
}
83

84
PyObject* TypePy::getParent(PyObject* args)
85
{
86
    if (!PyArg_ParseTuple(args, "")) {
87
        return nullptr;
88
    }
89

90
    Base::Type type = getBaseTypePtr()->getParent();
91
    return new TypePy(new Base::Type(type));
92
}
93

94
PyObject* TypePy::isBad(PyObject* args)
95
{
96
    if (!PyArg_ParseTuple(args, "")) {
97
        return nullptr;
98
    }
99

100
    bool val = getBaseTypePtr()->isBad();
101
    return PyBool_FromLong(val ? 1 : 0);
102
}
103

104
PyObject* TypePy::isDerivedFrom(PyObject* args)
105
{
106
    Base::Type type;
107

108
    do {
109
        const char* name {};
110
        if (PyArg_ParseTuple(args, "s", &name)) {
111
            type = Base::Type::fromName(name);
112
            break;
113
        }
114

115
        PyErr_Clear();
116
        PyObject* py {};
117
        if (PyArg_ParseTuple(args, "O!", &TypePy::Type, &py)) {
118
            type = *static_cast<TypePy*>(py)->getBaseTypePtr();
119
            break;
120
        }
121

122
        PyErr_SetString(PyExc_TypeError, "TypeId or str expected");
123
        return nullptr;
124
    } while (false);
125

126
    bool val = (type != Base::Type::badType() && getBaseTypePtr()->isDerivedFrom(type));
127
    return PyBool_FromLong(val ? 1 : 0);
128
}
129

130
PyObject* TypePy::getAllDerivedFrom(PyObject* args)
131
{
132
    Base::Type type;
133

134
    do {
135
        const char* name {};
136
        if (PyArg_ParseTuple(args, "s", &name)) {
137
            type = Base::Type::fromName(name);
138
            break;
139
        }
140

141
        PyErr_Clear();
142
        PyObject* py {};
143
        if (PyArg_ParseTuple(args, "O!", &TypePy::Type, &py)) {
144
            type = *static_cast<TypePy*>(py)->getBaseTypePtr();
145
            break;
146
        }
147

148
        PyErr_SetString(PyExc_TypeError, "TypeId or str expected");
149
        return nullptr;
150
    } while (false);
151

152
    std::vector<Base::Type> ary;
153
    Base::Type::getAllDerivedFrom(type, ary);
154
    Py::List res;
155
    for (const auto& it : ary) {
156
        res.append(Py::asObject(new TypePy(new Base::Type(it))));
157
    }
158
    return Py::new_reference_to(res);
159
}
160

161
PyObject* TypePy::getAllDerived(PyObject* args)
162
{
163
    if (!PyArg_ParseTuple(args, "")) {
164
        return nullptr;
165
    }
166

167
    Base::Type type = Base::Type::fromName(getBaseTypePtr()->getName());
168
    std::vector<Base::Type> ary;
169
    Base::Type::getAllDerivedFrom(type, ary);
170
    Py::List res;
171
    for (const auto& it : ary) {
172
        res.append(Py::asObject(new TypePy(new Base::Type(it))));
173
    }
174
    return Py::new_reference_to(res);
175
}
176

177
namespace
178
{
179
void deallocPyObject(PyObject* py)
180
{
181
    Base::PyObjectBase* pybase = static_cast<Base::PyObjectBase*>(py);
182
    Base::BaseClass* base = static_cast<Base::BaseClass*>(pybase->getTwinPointer());
183
    if (Base::BindingManager::instance().retrieveWrapper(base) == py) {
184
        Base::BindingManager::instance().releaseWrapper(base, py);
185
        delete base;
186
    }
187

188
    Base::PyObjectBase::PyDestructor(py);
189
}
190

191
PyObject* createPyObject(Base::BaseClass* base)
192
{
193
    PyObject* py = base->getPyObject();
194

195
    if (PyObject_TypeCheck(py, &Base::PyObjectBase::Type)) {
196
        // if the Python wrapper is a sub-class of PyObjectBase then
197
        // check if the C++ object must be added to the list of tracked objects
198
        Base::PyObjectBase* pybase = static_cast<Base::PyObjectBase*>(py);
199
        if (base == pybase->getTwinPointer()) {
200
            // steal a reference because at this point the counter is at 2
201
            Py_DECREF(py);
202
            Py_TYPE(py)->tp_dealloc = deallocPyObject;
203
            Base::BindingManager::instance().registerWrapper(base, py);
204
        }
205
        else {
206
            // The Python wrapper creates its own copy of the C++ object
207
            delete base;
208
        }
209
    }
210
    else {
211
        // if the Python wrapper is not a sub-class of PyObjectBase then
212
        // immediately destroy the C++ object
213
        delete base;
214
    }
215
    return py;
216
}
217

218
}  // namespace
219

220
PyObject* TypePy::createInstance(PyObject* args)
221
{
222
    if (!PyArg_ParseTuple(args, "")) {
223
        return nullptr;
224
    }
225

226
    Py::String name(getBaseTypePtr()->getName());
227
    Py::TupleN tuple(name);
228

229
    return createInstanceByName(tuple.ptr());
230
}
231

232
PyObject* TypePy::createInstanceByName(PyObject* args)
233
{
234
    const char* name {};
235
    PyObject* load = Py_False;  // NOLINT
236
    if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &load)) {
237
        return nullptr;
238
    }
239

240
    bool loadModule = Base::asBoolean(load);
241
    Base::Type type =
242
        Base::Type::getTypeIfDerivedFrom(name, Base::BaseClass::getClassTypeId(), loadModule);
243
    if (type.isBad()) {
244
        Py_Return;
245
    }
246

247
    void* typeInstance = type.createInstance();
248
    if (!typeInstance) {
249
        Py_Return;
250
    }
251

252
    Base::BaseClass* base = static_cast<Base::BaseClass*>(typeInstance);
253

254
    return createPyObject(base);
255
}
256

257
Py::String TypePy::getName() const
258
{
259
    return {std::string(getBaseTypePtr()->getName())};
260
}
261

262
Py::Long TypePy::getKey() const
263
{
264
    return Py::Long(static_cast<long>(getBaseTypePtr()->getKey()));
265
}
266

267
Py::String TypePy::getModule() const
268
{
269
    std::string module(getBaseTypePtr()->getName());
270
    std::string::size_type pos = module.find_first_of("::");
271

272
    if (pos != std::string::npos) {
273
        module = std::string(module, 0, pos);
274
    }
275
    else {
276
        module.clear();
277
    }
278

279
    return {module};
280
}
281

282
PyObject* TypePy::getCustomAttributes(const char* /*attr*/) const
283
{
284
    return nullptr;
285
}
286

287
int TypePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
288
{
289
    return 0;
290
}
291

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.