App: fix DocumentObjectPy::getSubObject:
* do not set pyMat to Py_None by default but nullptr and do type check in PyArg_ParseTupleAndKeywords * if refType is out of range raise a ValueError instead of TypeError * replace (undocumented) magic numbers with an enum class * implement a lambda function to avoid code duplication * fix bug for retType=3 or retType=4 if subname is a list of strings
This commit is contained in:
@@ -417,28 +417,41 @@ PyObject* DocumentObjectPy::getStatusString(PyObject *args)
|
||||
|
||||
PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
enum class ReturnType {
|
||||
PyObject = 0,
|
||||
DocObject = 1,
|
||||
DocAndPyObject = 2,
|
||||
Placement = 3,
|
||||
Matrix = 4,
|
||||
LinkAndPlacement = 5,
|
||||
LinkAndMatrix = 6
|
||||
};
|
||||
|
||||
PyObject *obj;
|
||||
short retType = 0;
|
||||
PyObject *pyMat = Py_None;
|
||||
PyObject *pyMat = nullptr;
|
||||
PyObject *doTransform = Py_True;
|
||||
short depth = 0;
|
||||
static char *kwlist[] = {"subname","retType","matrix","transform","depth", nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|hOOh", kwlist,
|
||||
&obj,&retType,&pyMat,&doTransform,&depth))
|
||||
|
||||
static char *kwlist[] = {"subname", "retType", "matrix", "transform", "depth", nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|hO!Oh", kwlist,
|
||||
&obj, &retType, &Base::MatrixPy::Type, &pyMat, &doTransform, &depth))
|
||||
return nullptr;
|
||||
|
||||
if (retType<0 || retType>6) {
|
||||
PyErr_SetString(PyExc_TypeError, "invalid retType, can only be integer 0~6");
|
||||
if (retType < 0 || retType > 6) {
|
||||
PyErr_SetString(PyExc_ValueError, "invalid retType, can only be integer 0~6");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReturnType retEnum = ReturnType(retType);
|
||||
std::vector<std::string> subs;
|
||||
bool single=true;
|
||||
bool single = true;
|
||||
|
||||
if (PyUnicode_Check(obj)) {
|
||||
subs.push_back(PyUnicode_AsUTF8(obj));
|
||||
}
|
||||
else if (PySequence_Check(obj)) {
|
||||
single=false;
|
||||
single = false;
|
||||
Py::Sequence shapeSeq(obj);
|
||||
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
|
||||
PyObject* item = (*it).ptr();
|
||||
@@ -467,11 +480,7 @@ PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds)
|
||||
};
|
||||
|
||||
Base::Matrix4D mat;
|
||||
if(pyMat!=Py_None) {
|
||||
if(!PyObject_TypeCheck(pyMat,&Base::MatrixPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expect argument 'matrix' to be of type Base.Matrix");
|
||||
return nullptr;
|
||||
}
|
||||
if (pyMat) {
|
||||
mat = *static_cast<Base::MatrixPy*>(pyMat)->getMatrixPtr();
|
||||
}
|
||||
|
||||
@@ -481,70 +490,59 @@ PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds)
|
||||
ret.emplace_back(mat);
|
||||
auto &info = ret.back();
|
||||
PyObject *pyObj = nullptr;
|
||||
info.sobj = getDocumentObjectPtr()->getSubObject(
|
||||
sub.c_str(),retType!=0&&retType!=2?nullptr:&pyObj,&info.mat,transform,depth);
|
||||
if(pyObj)
|
||||
info.pyObj = Py::Object(pyObj,true);
|
||||
if(info.sobj)
|
||||
info.obj = Py::Object(info.sobj->getPyObject(),true);
|
||||
|
||||
info.sobj = getDocumentObjectPtr()->getSubObject(sub.c_str(),
|
||||
retEnum != ReturnType::PyObject &&
|
||||
retEnum != ReturnType::DocAndPyObject ? nullptr : &pyObj,
|
||||
&info.mat, transform, depth);
|
||||
if (pyObj)
|
||||
info.pyObj = Py::asObject(pyObj);
|
||||
if (info.sobj)
|
||||
info.obj = Py::asObject(info.sobj->getPyObject());
|
||||
}
|
||||
if(ret.empty())
|
||||
|
||||
if (ret.empty())
|
||||
Py_Return;
|
||||
|
||||
if(single) {
|
||||
if(retType==0)
|
||||
return Py::new_reference_to(ret[0].pyObj);
|
||||
else if(retType==1 && pyMat==Py_None)
|
||||
return Py::new_reference_to(ret[0].obj);
|
||||
else if(!ret[0].sobj)
|
||||
Py_Return;
|
||||
else if(retType==3)
|
||||
return Py::new_reference_to(Py::Placement(Base::Placement(ret[0].mat)));
|
||||
else if(retType==4)
|
||||
return Py::new_reference_to(Py::Matrix(ret[0].mat));
|
||||
else if(retType==5 || retType==6) {
|
||||
ret[0].sobj->getLinkedObject(true,&ret[0].mat,false);
|
||||
if(retType==5)
|
||||
return Py::new_reference_to(Py::Placement(Base::Placement(ret[0].mat)));
|
||||
auto getReturnValue = [retEnum, pyMat](SubInfo& ret) -> Py::Object {
|
||||
if (retEnum == ReturnType::PyObject)
|
||||
return ret.pyObj;
|
||||
else if (retEnum == ReturnType::DocObject && !pyMat)
|
||||
return ret.obj;
|
||||
else if (!ret.sobj)
|
||||
return Py::None();
|
||||
else if (retEnum == ReturnType::Placement)
|
||||
return Py::Placement(Base::Placement(ret.mat));
|
||||
else if (retEnum == ReturnType::Matrix)
|
||||
return Py::Matrix(ret.mat);
|
||||
else if (retEnum == ReturnType::LinkAndPlacement || retEnum == ReturnType::LinkAndMatrix) {
|
||||
ret.sobj->getLinkedObject(true, &ret.mat, false);
|
||||
if (retEnum == ReturnType::LinkAndPlacement)
|
||||
return Py::Placement(Base::Placement(ret.mat));
|
||||
else
|
||||
return Py::new_reference_to(Py::Matrix(ret[0].mat));
|
||||
return Py::Matrix(ret.mat);
|
||||
}
|
||||
Py::Tuple rret(retType==1?2:3);
|
||||
rret.setItem(0,ret[0].obj);
|
||||
rret.setItem(1,Py::asObject(new Base::MatrixPy(ret[0].mat)));
|
||||
if(retType!=1)
|
||||
rret.setItem(2,ret[0].pyObj);
|
||||
return Py::new_reference_to(rret);
|
||||
else {
|
||||
Py::Tuple rret(retEnum == ReturnType::DocObject ? 2 : 3);
|
||||
rret.setItem(0, ret.obj);
|
||||
rret.setItem(1, Py::asObject(new Base::MatrixPy(ret.mat)));
|
||||
if (retEnum != ReturnType::DocObject)
|
||||
rret.setItem(2, ret.pyObj);
|
||||
return rret;
|
||||
}
|
||||
};
|
||||
|
||||
if (single) {
|
||||
return Py::new_reference_to(getReturnValue(ret[0]));
|
||||
}
|
||||
|
||||
Py::Tuple tuple(ret.size());
|
||||
for(size_t i=0;i<ret.size();++i) {
|
||||
if(retType==0)
|
||||
tuple.setItem(i,ret[i].pyObj);
|
||||
else if(retType==1 && pyMat==Py_None)
|
||||
tuple.setItem(i,ret[i].obj);
|
||||
else if(!ret[i].sobj)
|
||||
tuple.setItem(i, Py::Object());
|
||||
else if(retType==3)
|
||||
tuple.setItem(i,Py::Placement(Base::Placement(ret[0].mat)));
|
||||
else if(retType==4)
|
||||
tuple.setItem(i,Py::Matrix(ret[0].mat));
|
||||
else if(retType==5 || retType==6) {
|
||||
ret[i].sobj->getLinkedObject(true,&ret[i].mat,false);
|
||||
if(retType==5)
|
||||
tuple.setItem(i,Py::Placement(Base::Placement(ret[i].mat)));
|
||||
else
|
||||
tuple.setItem(i,Py::Matrix(ret[i].mat));
|
||||
} else {
|
||||
Py::Tuple rret(retType==1?2:3);
|
||||
rret.setItem(0,ret[i].obj);
|
||||
rret.setItem(1,Py::asObject(new Base::MatrixPy(ret[i].mat)));
|
||||
if(retType!=1)
|
||||
rret.setItem(2,ret[i].pyObj);
|
||||
tuple.setItem(i,rret);
|
||||
}
|
||||
for(size_t i=0; i<ret.size(); ++i) {
|
||||
tuple.setItem(i, getReturnValue(ret[i]));
|
||||
}
|
||||
return Py::new_reference_to(tuple);
|
||||
}PY_CATCH
|
||||
}
|
||||
PY_CATCH
|
||||
}
|
||||
|
||||
PyObject* DocumentObjectPy::getSubObjectList(PyObject *args) {
|
||||
|
||||
Reference in New Issue
Block a user