FreeCAD

Форк
0
/
LinkBaseExtensionPyImp.cpp 
300 строк · 10.3 Кб
1
/****************************************************************************
2
 *   Copyright (c) 2017 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
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., 59 Temple Place,          *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                 *
20
 *                                                                          *
21
 ****************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <sstream>
27
#endif
28

29
#include "DocumentObjectPy.h"
30
#include "LinkBaseExtensionPy.h"
31
#include "LinkBaseExtensionPy.cpp"
32

33
using namespace App;
34

35
// returns a string which represent the object e.g. when printed in python
36
std::string LinkBaseExtensionPy::representation() const
37
{
38
    std::ostringstream str;
39
    str << "<" << getLinkBaseExtensionPtr()->getExtensionClassTypeId().getName() << ">";
40
    return str.str();
41
}
42

43
using PropTmpMap = std::map<std::string, std::pair<int,Property*> >;
44
using PropMap = std::map<std::string, Property*>;
45

46
static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap &infoMap,
47
        const PropMap &propMap, PyObject *key, PyObject *value)
48
{
49
    std::ostringstream str;
50

51
    if(!PyUnicode_Check(key)) {
52
        PyErr_SetString(PyExc_TypeError, "key must be a unicode string");
53
        return false;
54
    }
55
    const char *keyStr = PyUnicode_AsUTF8(key);
56
    auto it = infoMap.find(keyStr);
57
    if(it == infoMap.end()){
58
        str << "unknown key '" << keyStr << "'";
59
        PyErr_SetString(PyExc_KeyError, str.str().c_str());
60
        return false;
61
    }
62

63
    const char *valStr = nullptr;
64
    if(key == value)
65
        valStr = keyStr;
66
    else if (value!=Py_None) {
67
        if(!PyUnicode_Check(value)) {
68
            PyErr_SetString(PyExc_TypeError, "value must be unicode string");
69
            return false;
70
        }
71
        valStr = PyUnicode_AsUTF8(value);
72
    }
73

74
    App::Property *prop = nullptr;
75
    auto &info = it->second;
76
    if(valStr) {
77
        auto pIt = propMap.find(valStr);
78
        if(pIt == propMap.end()) {
79
            str << "cannot find property '" << valStr << "'";
80
            PyErr_SetString(PyExc_ValueError, str.str().c_str());
81
            return false;
82
        }
83
        prop = pIt->second;
84
        if(!prop->isDerivedFrom(info.type)) {
85
            str << "expect property '" << keyStr << "(" << valStr
86
                << ") to be derived from '" << info.type.getName()
87
                << "', instead of '" << prop->getTypeId().getName() << "'";
88
            PyErr_SetString(PyExc_TypeError, str.str().c_str());
89
        }
90
    }
91
    props[keyStr] = std::make_pair(info.index,prop);
92
    return true;
93
}
94

95
PyObject* LinkBaseExtensionPy::configLinkProperty(PyObject *args, PyObject *keywds) {
96
    auto ext = getLinkBaseExtensionPtr();
97
    const auto &info = ext->getPropertyInfoMap();
98

99
    PropMap propMap;
100
    ext->getExtendedContainer()->getPropertyMap(propMap);
101

102
    PropTmpMap props;
103

104
    if(args && PyTuple_Check(args)) {
105
        for(Py_ssize_t pos=0;pos<PyTuple_GET_SIZE(args);++pos) {
106
            auto key = PyTuple_GET_ITEM(args,pos);
107
            if(!getProperty(props,info,propMap,key,key))
108
                return nullptr;
109
        }
110
    }
111
    if(keywds && PyDict_Check(keywds)) {
112
        PyObject *key, *value;
113
        Py_ssize_t pos = 0;
114
        while (PyDict_Next(keywds, &pos, &key, &value)) {
115
            if(!getProperty(props,info,propMap,key,value))
116
                return nullptr;
117
        }
118
    }
119
    for(auto &v : props)
120
        ext->setProperty(v.second.first,v.second.second);
121
    Py_Return;
122
}
123

124
PyObject* LinkBaseExtensionPy::getLinkExtProperty(PyObject *args)
125
{
126
    const char *name;
127
    if(!PyArg_ParseTuple(args,"s",&name))
128
        return nullptr;
129
    auto prop = getLinkBaseExtensionPtr()->getProperty(name);
130
    if(!prop) {
131
        PyErr_SetString(PyExc_AttributeError, "unknown property name");
132
        return nullptr;
133
    }
134
    return prop->getPyObject();
135
}
136

137
PyObject* LinkBaseExtensionPy::getLinkExtPropertyName(PyObject *args) {
138
    const char *name;
139
    if(!PyArg_ParseTuple(args,"s",&name))
140
        return nullptr;
141
    auto prop = getLinkBaseExtensionPtr()->getProperty(name);
142
    if(!prop) {
143
        PyErr_SetString(PyExc_AttributeError, "unknown property name");
144
        return nullptr;
145
    }
146
    auto container = getLinkBaseExtensionPtr()->getExtendedContainer();
147
    if(!container) {
148
        PyErr_SetString(PyExc_RuntimeError, "no extended container");
149
        return nullptr;
150
    }
151
    name = container->getPropertyName(prop);
152
    if(!name) {
153
        PyErr_SetString(PyExc_RuntimeError, "cannot find property name");
154
        return nullptr;
155
    }
156
    return Py::new_reference_to(Py::String(name));
157
}
158

159
PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject *args)
160
{
161
    auto ext = getLinkBaseExtensionPtr();
162

163
    const auto &infos = ext->getPropertyInfo();
164

165
    if(PyArg_ParseTuple(args,"")) {
166
        Py::Tuple ret(infos.size());
167
        int i=0;
168
        for(const auto &info : infos) {
169
            ret.setItem(i++,Py::TupleN(Py::String(info.name),
170
                    Py::String(info.type.getName()),Py::String(info.doc)));
171
        }
172
        return Py::new_reference_to(ret);
173
    }
174

175
    short index = 0;
176
    if(PyArg_ParseTuple(args,"h",&index)) {
177
        if(index<0 || index>=(int)infos.size()) {
178
            PyErr_SetString(PyExc_ValueError, "index out of range");
179
            return nullptr;
180
        }
181
        Py::TupleN ret(Py::String(infos[index].name),
182
                Py::String(infos[index].type.getName()),Py::String(infos[index].doc));
183
        return Py::new_reference_to(ret);
184
    }
185

186
    char *name;
187
    if(PyArg_ParseTuple(args,"s",&name)) {
188
        for(const auto & info : infos) {
189
            if(strcmp(info.name,name)==0) {
190
                Py::TupleN ret(Py::String(info.type.getName()),
191
                               Py::String(info.doc));
192
                return Py::new_reference_to(ret);
193
            }
194
        }
195
        PyErr_SetString(PyExc_ValueError, "unknown property name");
196
        return nullptr;
197
    }
198

199
    PyErr_SetString(PyExc_ValueError, "invalid arguments");
200
    return nullptr;
201
}
202

203
void parseLink(LinkBaseExtension *ext, int index, PyObject *value) {
204
    App::DocumentObject *obj = nullptr;
205
    PropertyStringList subs;
206
    PropertyString sub;
207
    if(value!=Py_None) {
208
        if(PyObject_TypeCheck(value,&DocumentObjectPy::Type)) {
209
            obj = static_cast<DocumentObjectPy*>(value)->getDocumentObjectPtr();
210
        }else if(!PySequence_Check(value))
211
            throw Base::TypeError("Expects type of DocumentObject or sequence");
212
        else{
213
            Py::Sequence seq(value);
214
            if(seq[0].ptr() != Py_None) {
215
                if(!PyObject_TypeCheck(seq[0].ptr(),&DocumentObjectPy::Type))
216
                    throw Base::TypeError("Expects the first argument to be DocumentObject in sequence");
217
                obj = static_cast<DocumentObjectPy*>(seq[0].ptr())->getDocumentObjectPtr();
218
                if(seq.size()>1) {
219
                    sub.setPyObject(seq[1].ptr());
220
                    if(seq.size()>2)
221
                        subs.setPyObject(seq[2].ptr());
222
                }
223
            }
224
        }
225
    }
226
    ext->setLink(index,obj,sub.getValue(),subs.getValue());
227
}
228

229
PyObject* LinkBaseExtensionPy::setLink(PyObject *_args)
230
{
231
    Py::Sequence args(_args);
232
    PY_TRY {
233
        auto ext = getLinkBaseExtensionPtr();
234
        PyObject *pcObj = args.size()?args[0].ptr():Py_None;
235
        if(pcObj == Py_None) {
236
            ext->setLink(-1,nullptr);
237
        }else if(PyDict_Check(pcObj)) {
238
            PyObject *key, *value;
239
            Py_ssize_t pos = 0;
240
            while(PyDict_Next(pcObj, &pos, &key, &value))
241
                parseLink(ext,Py::Int(key),value);
242
        }else if(PySequence_Check(pcObj)) {
243
            ext->setLink(-1,nullptr);
244
            Py::Sequence seq(pcObj);
245
            for(Py_ssize_t i=0;i<seq.size();++i)
246
                parseLink(ext,i,seq[i].ptr());
247
        }else
248
            parseLink(ext,-1,_args);
249

250
        Py_Return;
251
    }PY_CATCH
252
}
253

254
PyObject* LinkBaseExtensionPy::cacheChildLabel(PyObject *args) {
255
    PyObject *enable = Py_True;
256
    if(!PyArg_ParseTuple(args,"|O",&enable))
257
        return nullptr;
258
    PY_TRY {
259
        getLinkBaseExtensionPtr()->cacheChildLabel(Base::asBoolean(enable) ? -1 : 0);
260
        Py_Return;
261
    }PY_CATCH;
262
}
263

264
PyObject* LinkBaseExtensionPy::flattenSubname(PyObject *args) {
265
    const char *subname;
266
    if(!PyArg_ParseTuple(args,"s",&subname))
267
        return nullptr;
268
    PY_TRY {
269
        return Py::new_reference_to(Py::String(
270
                    getLinkBaseExtensionPtr()->flattenSubname(subname)));
271
    }PY_CATCH;
272
}
273

274
PyObject* LinkBaseExtensionPy::expandSubname(PyObject *args) {
275
    const char *subname;
276
    if(!PyArg_ParseTuple(args,"s",&subname))
277
        return nullptr;
278
    PY_TRY {
279
        std::string sub(subname);
280
        getLinkBaseExtensionPtr()->expandSubname(sub);
281
        return Py::new_reference_to(Py::String(sub));
282
    }PY_CATCH;
283
}
284

285
Py::List LinkBaseExtensionPy::getLinkedChildren() const {
286
    Py::List ret;
287
    for(auto o : getLinkBaseExtensionPtr()->getLinkedChildren(true))
288
        ret.append(Py::asObject(o->getPyObject()));
289
    return ret;
290
}
291

292
PyObject *LinkBaseExtensionPy::getCustomAttributes(const char* /*attr*/) const
293
{
294
    return nullptr;
295
}
296

297
int LinkBaseExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject * /*obj*/)
298
{
299
    return 0;
300
}
301

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

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

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

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