FreeCAD / src /App /DocumentPyImp.cpp
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2007 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include <Base/FileInfo.h>
#include <Base/Interpreter.h>
#include <Base/Stream.h>
#include "Document.h"
#include "DocumentObject.h"
#include "DocumentObjectPy.h"
#include "MergeDocuments.h"
// inclusion of the generated files (generated By DocumentPy.xml)
#include "DocumentPy.h"
#include "DocumentPy.cpp"
#include <boost/regex.hpp>
#include <Base/PyWrapParseTupleAndKeywords.h>
using namespace App;
PyObject* DocumentPy::addProperty(PyObject* args, PyObject* kwd)
{
char* sType {nullptr};
char* sName {nullptr};
char* sGroup {nullptr};
char* sDoc {nullptr};
short attr = 0;
std::string sDocStr;
PyObject *ro = Py_False, *hd = Py_False, *lk = Py_False;
PyObject* enumVals = nullptr;
static const std::array<const char*, 10> kwlist {"type",
"name",
"group",
"doc",
"attr",
"read_only",
"hidden",
"locked",
"enum_vals",
nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args,
kwd,
"ss|sethO!O!O!O",
kwlist,
&sType,
&sName,
&sGroup,
"utf-8",
&sDoc,
&attr,
&PyBool_Type,
&ro,
&PyBool_Type,
&hd,
&PyBool_Type,
&lk,
&enumVals)) {
return nullptr;
}
if (sDoc) {
sDocStr = sDoc;
PyMem_Free(sDoc);
}
Property* prop = getDocumentPtr()->addDynamicProperty(sType,
sName,
sGroup,
sDocStr.c_str(),
attr,
Base::asBoolean(ro),
Base::asBoolean(hd));
prop->setStatus(Property::LockDynamic, Base::asBoolean(lk));
// enum support
auto* propEnum = dynamic_cast<App::PropertyEnumeration*>(prop);
if (propEnum && enumVals) {
propEnum->setPyObject(enumVals);
}
return Py::new_reference_to(this);
}
PyObject* DocumentPy::removeProperty(PyObject* args)
{
char* sName;
if (!PyArg_ParseTuple(args, "s", &sName)) {
return nullptr;
}
bool ok = getDocumentPtr()->removeDynamicProperty(sName);
return Py_BuildValue("O", (ok ? Py_True : Py_False));
}
// returns a string which represent the object e.g. when printed in python
std::string DocumentPy::representation() const
{
std::stringstream str;
str << "<Document '" << getDocumentPtr()->getName() << "' (" << getDocumentPtr()->Label.getValue() << ") >";
return str.str();
}
PyObject* DocumentPy::save(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
PY_TRY
{
if (!getDocumentPtr()->save()) {
PyErr_SetString(PyExc_ValueError, "Object attribute 'FileName' is not set");
return nullptr;
}
}
PY_CATCH;
const char* filename = getDocumentPtr()->FileName.getValue();
Base::FileInfo fi(filename);
if (!fi.isReadable()) {
PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
return nullptr;
}
Py_Return;
}
PyObject* DocumentPy::saveAs(PyObject* args)
{
char* fn;
if (!PyArg_ParseTuple(args, "et", "utf-8", &fn)) {
return nullptr;
}
std::string utf8Name = fn;
PyMem_Free(fn);
PY_TRY
{
getDocumentPtr()->saveAs(utf8Name.c_str());
Py_Return;
}
PY_CATCH
}
PyObject* DocumentPy::saveCopy(PyObject* args)
{
char* fn;
if (!PyArg_ParseTuple(args, "s", &fn)) {
return nullptr;
}
PY_TRY
{
getDocumentPtr()->saveCopy(fn);
Py_Return;
}
PY_CATCH
}
PyObject* DocumentPy::load(PyObject* args)
{
char* filename = nullptr;
if (!PyArg_ParseTuple(args, "s", &filename)) {
return nullptr;
}
if (!filename || *filename == '\0') {
PyErr_Format(PyExc_ValueError, "Path is empty");
return nullptr;
}
getDocumentPtr()->FileName.setValue(filename);
Base::FileInfo fi(filename);
if (!fi.isReadable()) {
PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
return nullptr;
}
try {
getDocumentPtr()->restore();
}
catch (...) {
PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
return nullptr;
}
Py_Return;
}
PyObject* DocumentPy::restore(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
const char* filename = getDocumentPtr()->FileName.getValue();
if (!filename || *filename == '\0') {
PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
return nullptr;
}
Base::FileInfo fi(filename);
if (!fi.isReadable()) {
PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
return nullptr;
}
try {
getDocumentPtr()->restore();
}
catch (...) {
PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
return nullptr;
}
Py_Return;
}
PyObject* DocumentPy::isSaved(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
bool ok = getDocumentPtr()->isSaved();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* DocumentPy::getProgramVersion(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
const char* version = getDocumentPtr()->getProgramVersion();
return Py::new_reference_to(Py::String(version));
}
PyObject* DocumentPy::getFileName(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
const char* fn = getDocumentPtr()->getFileName();
return Py::new_reference_to(Py::String(fn));
}
PyObject* DocumentPy::getUniqueObjectName(PyObject* args)
{
char* sName;
if (!PyArg_ParseTuple(args, "s", &sName)) {
return nullptr;
}
PY_TRY
{
auto newName = getDocumentPtr()->getUniqueObjectName(sName);
return Py::new_reference_to(Py::String(newName));
}
PY_CATCH;
}
PyObject* DocumentPy::mergeProject(PyObject* args)
{
char* filename;
if (!PyArg_ParseTuple(args, "s", &filename)) {
return nullptr;
}
PY_TRY
{
Base::FileInfo fi(filename);
Base::ifstream str(fi, std::ios::in | std::ios::binary);
App::Document* doc = getDocumentPtr();
MergeDocuments md(doc);
md.importObjects(str);
Py_Return;
}
PY_CATCH;
}
PyObject* DocumentPy::exportGraphviz(PyObject* args)
{
char* fn = nullptr;
if (!PyArg_ParseTuple(args, "|s", &fn)) {
return nullptr;
}
if (fn) {
Base::FileInfo fi(fn);
Base::ofstream str(fi);
getDocumentPtr()->exportGraphviz(str);
str.close();
Py_Return;
}
else {
std::stringstream str;
getDocumentPtr()->exportGraphviz(str);
return PyUnicode_FromString(str.str().c_str());
}
}
PyObject* DocumentPy::addObject(PyObject* args, PyObject* kwd)
{
char *sType, *sName = nullptr, *sViewType = nullptr;
PyObject* obj = nullptr;
PyObject* view = nullptr;
PyObject* attach = Py_False;
static const std::array<const char*, 7>
kwlist {"type", "name", "objProxy", "viewProxy", "attach", "viewType", nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args,
kwd,
"s|sOOO!s",
kwlist,
&sType,
&sName,
&obj,
&view,
&PyBool_Type,
&attach,
&sViewType)) {
return nullptr;
}
DocumentObject* pcFtr = nullptr;
if (!obj || !Base::asBoolean(attach)) {
pcFtr = getDocumentPtr()->addObject(sType, sName, true, sViewType);
}
else {
Base::Type type =
Base::Type::getTypeIfDerivedFrom(sType, DocumentObject::getClassTypeId(), true);
if (type.isBad()) {
std::stringstream str;
str << "'" << sType << "' is not a document object type";
throw Base::TypeError(str.str());
}
pcFtr = static_cast<DocumentObject*>(type.createInstance());
}
// the type instance could be a null pointer
if (!pcFtr) {
std::stringstream str;
str << "No document object found of type '" << sType << "'" << std::ends;
throw Py::TypeError(str.str());
}
// Allows one to hide the handling with Proxy in client python code
if (obj) {
try {
// the python binding class to the document object
Py::Object pyftr = Py::asObject(pcFtr->getPyObject());
// 'pyobj' is the python class with the implementation for DocumentObject
Py::Object pyobj(obj);
if (pyobj.hasAttr("__object__")) {
pyobj.setAttr("__object__", pyftr);
}
pyftr.setAttr("Proxy", pyobj);
if (Base::asBoolean(attach)) {
getDocumentPtr()->addObject(pcFtr, sName);
try {
Py::Callable method(pyobj.getAttr("attach"));
if (!method.isNone()) {
Py::TupleN arg(pyftr);
method.apply(arg);
}
}
catch (Py::Exception&) {
Base::PyException e;
e.reportException();
}
}
// if a document class is set we also need a view provider defined which must be
// something different to None
Py::Object pyvp;
if (view) {
pyvp = Py::Object(view);
}
if (pyvp.isNone()) {
pyvp = Py::Long(1);
}
// 'pyvp' is the python class with the implementation for ViewProvider
if (pyvp.hasAttr("__vobject__")) {
pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject"));
}
Py::Object pyprx(pyftr.getAttr("ViewObject"));
pyprx.setAttr("Proxy", pyvp);
return Py::new_reference_to(pyftr);
}
catch (Py::Exception& e) {
e.clear();
}
}
return pcFtr->getPyObject();
}
PyObject* DocumentPy::removeObject(PyObject* args)
{
char* sName;
if (!PyArg_ParseTuple(args, "s", &sName)) {
return nullptr;
}
DocumentObject* pcFtr = getDocumentPtr()->getObject(sName);
if (pcFtr) {
getDocumentPtr()->removeObject(sName);
Py_Return;
}
else {
std::stringstream str;
str << "No document object found with name '" << sName << "'" << std::ends;
throw Py::ValueError(str.str());
}
}
PyObject* DocumentPy::copyObject(PyObject* args, PyObject* kwd)
{
PyObject* obj;
PyObject* rec = Py_False;
PyObject* retAll = Py_False;
static constexpr std::array<const char*, 4> kwlist {"object", "recursive", "return_all", nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args,
kwd,
"O|O!O!",
kwlist,
&obj,
&PyBool_Type,
&rec,
&PyBool_Type,
&retAll)) {
return nullptr;
}
std::vector<App::DocumentObject*> objs;
bool single = false;
if (PySequence_Check(obj)) {
Py::Sequence seq(obj);
for (Py_ssize_t i = 0; i < seq.size(); ++i) {
if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
PyErr_SetString(PyExc_TypeError,
"Expect element in sequence to be of type document object");
return nullptr;
}
objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
}
}
else if (!PyObject_TypeCheck(obj, &DocumentObjectPy::Type)) {
PyErr_SetString(
PyExc_TypeError,
"Expect first argument to be either a document object or sequence of document objects");
return nullptr;
}
else {
objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
single = true;
}
PY_TRY
{
auto ret =
getDocumentPtr()->copyObject(objs, Base::asBoolean(rec), Base::asBoolean(retAll));
if (ret.size() == 1 && single) {
return ret[0]->getPyObject();
}
Py::Tuple tuple(ret.size());
for (size_t i = 0; i < ret.size(); ++i) {
tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true));
}
return Py::new_reference_to(tuple);
}
PY_CATCH
}
PyObject* DocumentPy::importLinks(PyObject* args)
{
PyObject* obj = Py_None;
if (!PyArg_ParseTuple(args, "|O", &obj)) {
return nullptr;
}
std::vector<App::DocumentObject*> objs;
if (PySequence_Check(obj)) {
Py::Sequence seq(obj);
for (Py_ssize_t i = 0; i < seq.size(); ++i) {
if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
PyErr_SetString(PyExc_TypeError,
"Expect element in sequence to be of type document object");
return nullptr;
}
objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
}
}
else {
Base::PyTypeCheck(&obj,
&DocumentObjectPy::Type,
"Expect first argument to be either a document object, sequence of "
"document objects or None");
if (obj) {
objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
}
}
if (objs.empty()) {
objs = getDocumentPtr()->getObjects();
}
PY_TRY
{
auto ret = getDocumentPtr()->importLinks(objs);
Py::Tuple tuple(ret.size());
for (size_t i = 0; i < ret.size(); ++i) {
tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true));
}
return Py::new_reference_to(tuple);
}
PY_CATCH
}
PyObject* DocumentPy::moveObject(PyObject* args)
{
PyObject *obj, *rec = Py_False;
if (!PyArg_ParseTuple(args, "O!|O!", &(DocumentObjectPy::Type), &obj, &PyBool_Type, &rec)) {
return nullptr;
}
DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(obj);
DocumentObject* move =
getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), Base::asBoolean(rec));
if (move) {
return move->getPyObject();
}
else {
std::string str("Failed to move the object");
throw Py::ValueError(str);
}
}
PyObject* DocumentPy::openTransaction(PyObject* args)
{
PyObject* value = nullptr;
if (!PyArg_ParseTuple(args, "|O", &value)) {
return nullptr;
}
std::string cmd;
if (!value) {
cmd = "<empty>";
}
else if (PyUnicode_Check(value)) {
cmd = PyUnicode_AsUTF8(value);
}
else {
PyErr_SetString(PyExc_TypeError, "string or unicode expected");
return nullptr;
}
getDocumentPtr()->openTransaction(cmd.c_str());
Py_Return;
}
PyObject* DocumentPy::abortTransaction(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
getDocumentPtr()->abortTransaction();
Py_Return;
}
PyObject* DocumentPy::commitTransaction(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
getDocumentPtr()->commitTransaction();
Py_Return;
}
Py::Boolean DocumentPy::getHasPendingTransaction() const
{
return {getDocumentPtr()->hasPendingTransaction()};
}
PyObject* DocumentPy::undo(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
if (getDocumentPtr()->getAvailableUndos()) {
getDocumentPtr()->undo();
}
Py_Return;
}
PyObject* DocumentPy::redo(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
if (getDocumentPtr()->getAvailableRedos()) {
getDocumentPtr()->redo();
}
Py_Return;
}
PyObject* DocumentPy::clearUndos(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
getDocumentPtr()->clearUndos();
Py_Return;
}
PyObject* DocumentPy::clearDocument(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
getDocumentPtr()->clearDocument();
Py_Return;
}
PyObject* DocumentPy::setClosable(PyObject* args)
{
PyObject* close;
if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &close)) {
return nullptr;
}
getDocumentPtr()->setClosable(Base::asBoolean(close));
Py_Return;
}
PyObject* DocumentPy::isClosable(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
bool ok = getDocumentPtr()->isClosable();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject *DocumentPy::setAutoCreated(PyObject *args)
{
PyObject *autoCreated;
if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &autoCreated)) {
return nullptr;
}
bool value = (autoCreated == Py_True);
getDocumentPtr()->setAutoCreated(value);
Py_RETURN_NONE;
}
PyObject *DocumentPy::isAutoCreated(PyObject *args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
bool ok = getDocumentPtr()->isAutoCreated();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* DocumentPy::recompute(PyObject* args)
{
PyObject* pyobjs = Py_None;
PyObject* force = Py_False;
PyObject* checkCycle = Py_False;
if (!PyArg_ParseTuple(args,
"|OO!O!",
&pyobjs,
&PyBool_Type,
&force,
&PyBool_Type,
&checkCycle)) {
return nullptr;
}
PY_TRY
{
std::vector<App::DocumentObject*> objs;
if (pyobjs != Py_None) {
if (!PySequence_Check(pyobjs)) {
PyErr_SetString(PyExc_TypeError, "expect input of sequence of document objects");
return nullptr;
}
Py::Sequence seq(pyobjs);
for (Py_ssize_t i = 0; i < seq.size(); ++i) {
if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
PyErr_SetString(PyExc_TypeError,
"Expect element in sequence to be of type document object");
return nullptr;
}
objs.push_back(
static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
}
}
int options = 0;
if (Base::asBoolean(checkCycle)) {
options = Document::DepNoCycle;
}
int objectCount =
getDocumentPtr()->recompute(objs, Base::asBoolean(force), nullptr, options);
// Document::recompute() hides possibly raised Python exceptions by its features
// So, check if an error is set and return null if yes
if (PyErr_Occurred()) {
return nullptr;
}
return Py::new_reference_to(Py::Long(objectCount));
}
PY_CATCH;
}
PyObject* DocumentPy::mustExecute(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
bool ok = getDocumentPtr()->mustExecute();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* DocumentPy::isTouched(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
bool ok = getDocumentPtr()->isTouched();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* DocumentPy::purgeTouched(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
getDocumentPtr()->purgeTouched();
Py_Return;
}
PyObject* DocumentPy::getObject(PyObject* args)
{
DocumentObject* obj = nullptr;
do {
char* name = nullptr;
if (PyArg_ParseTuple(args, "s", &name)) {
obj = getDocumentPtr()->getObject(name);
break;
}
PyErr_Clear();
long id = -1;
if (PyArg_ParseTuple(args, "l", &id)) {
obj = getDocumentPtr()->getObjectByID(id);
break;
}
PyErr_SetString(PyExc_TypeError, "a string or integer is required");
return nullptr;
} while (false);
if (obj) {
return obj->getPyObject();
}
Py_Return;
}
PyObject* DocumentPy::getObjectsByLabel(PyObject* args)
{
char* sName;
if (!PyArg_ParseTuple(args, "s", &sName)) {
return nullptr;
}
Py::List list;
std::string name = sName;
std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
for (auto obj : objs) {
if (name == obj->Label.getValue()) {
list.append(Py::asObject(obj->getPyObject()));
}
}
return Py::new_reference_to(list);
}
PyObject* DocumentPy::findObjects(PyObject* args, PyObject* kwds)
{
const char *sType = "App::DocumentObject", *sName = nullptr, *sLabel = nullptr;
static const std::array<const char*, 4> kwlist {"Type", "Name", "Label", nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "|sss", kwlist, &sType, &sName, &sLabel)) {
return nullptr;
}
Base::Type type =
Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true);
if (type.isBad()) {
std::stringstream str;
str << "'" << sType << "' is not a document object type";
throw Base::TypeError(str.str());
}
std::vector<DocumentObject*> res;
try {
res = getDocumentPtr()->findObjects(type, sName, sLabel);
}
catch (const boost::regex_error& e) {
PyErr_SetString(PyExc_RuntimeError, e.what());
return nullptr;
}
Py_ssize_t index = 0;
PyObject* list = PyList_New((Py_ssize_t)res.size());
for (std::vector<DocumentObject*>::const_iterator It = res.begin(); It != res.end();
++It, index++) {
PyList_SetItem(list, index, (*It)->getPyObject());
}
return list;
}
Py::Object DocumentPy::getActiveObject() const
{
DocumentObject* pcFtr = getDocumentPtr()->getActiveObject();
if (pcFtr) {
return Py::Object(pcFtr->getPyObject(), true);
}
return Py::None();
}
PyObject* DocumentPy::supportedTypes(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
std::vector<Base::Type> ary;
Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary);
Py::List res;
for (const auto& it : ary) {
res.append(Py::String(it.getName()));
}
return Py::new_reference_to(res);
}
Py::List DocumentPy::getObjects() const
{
std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
Py::List res;
for (auto obj : objs) {
// Note: Here we must force the Py::Object to own this Python object as getPyObject()
// increments the counter
res.append(Py::Object(obj->getPyObject(), true));
}
return res;
}
Py::List DocumentPy::getTopologicalSortedObjects() const
{
std::vector<DocumentObject*> objs = getDocumentPtr()->topologicalSort();
Py::List res;
for (auto obj : objs) {
// Note: Here we must force the Py::Object to own this Python object as getPyObject()
// increments the counter
res.append(Py::Object(obj->getPyObject(), true));
}
return res;
}
Py::List DocumentPy::getRootObjects() const
{
std::vector<DocumentObject*> objs = getDocumentPtr()->getRootObjects();
Py::List res;
for (auto obj : objs) {
// Note: Here we must force the Py::Object to own this Python object as getPyObject()
// increments the counter
res.append(Py::Object(obj->getPyObject(), true));
}
return res;
}
Py::List DocumentPy::getRootObjectsIgnoreLinks() const
{
std::vector<App::DocumentObject*> objs = getDocumentPtr()->getRootObjectsIgnoreLinks();
Py::List res;
for (auto obj : objs) {
// Note: Here we must force the Py::Object to own this Python object as getPyObject()
// increments the counter
res.append(Py::Object(obj->getPyObject(), true));
}
return res;
}
Py::Long DocumentPy::getUndoMode() const
{
return Py::Long(getDocumentPtr()->getUndoMode());
}
void DocumentPy::setUndoMode(Py::Long arg)
{
getDocumentPtr()->setUndoMode(arg);
}
Py::Long DocumentPy::getUndoRedoMemSize() const
{
return Py::Long((long)getDocumentPtr()->getUndoMemSize());
}
Py::Long DocumentPy::getUndoCount() const
{
return Py::Long((long)getDocumentPtr()->getAvailableUndos());
}
Py::Long DocumentPy::getRedoCount() const
{
return Py::Long((long)getDocumentPtr()->getAvailableRedos());
}
Py::List DocumentPy::getUndoNames() const
{
std::vector<std::string> vList = getDocumentPtr()->getAvailableUndoNames();
Py::List res;
for (const auto& It : vList) {
res.append(Py::String(It));
}
return res;
}
Py::List DocumentPy::getRedoNames() const
{
std::vector<std::string> vList = getDocumentPtr()->getAvailableRedoNames();
Py::List res;
for (const auto& It : vList) {
res.append(Py::String(It));
}
return res;
}
Py::String DocumentPy::getDependencyGraph() const
{
std::stringstream out;
getDocumentPtr()->exportGraphviz(out);
return {out.str()};
}
Py::String DocumentPy::getName() const
{
return {getDocumentPtr()->getName()};
}
Py::Boolean DocumentPy::getRecomputesFrozen() const
{
return {getDocumentPtr()->testStatus(Document::Status::SkipRecompute)};
}
void DocumentPy::setRecomputesFrozen(Py::Boolean arg)
{
getDocumentPtr()->setStatus(Document::Status::SkipRecompute, arg.isTrue());
}
PyObject* DocumentPy::getTempFileName(PyObject* args)
{
PyObject* value;
if (!PyArg_ParseTuple(args, "O", &value)) {
return nullptr;
}
std::string string;
if (PyUnicode_Check(value)) {
string = PyUnicode_AsUTF8(value);
}
else {
std::string error = std::string("type must be a string!");
error += value->ob_type->tp_name;
throw Py::TypeError(error);
}
// search for a temp file name in the document transient directory
Base::FileInfo fileName(
Base::FileInfo::getTempFileName(string.c_str(), getDocumentPtr()->TransientDir.getValue()));
// delete the created file, we need only the name...
fileName.deleteFile();
PyObject* p =
PyUnicode_DecodeUTF8(fileName.filePath().c_str(), fileName.filePath().size(), nullptr);
if (!p) {
throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()");
}
return p;
}
PyObject* DocumentPy::getCustomAttributes(const char* attr) const
{
// Note: Here we want to return only a document object if its
// name matches 'attr'. However, it is possible to have an object
// with the same name as an attribute. If so, we return 0 as other-
// wise it wouldn't be possible to address this attribute any more.
// The object must then be addressed by the getObject() method directly.
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
if (prop) {
return nullptr;
}
if (!this->ob_type->tp_dict) {
if (PyType_Ready(this->ob_type) < 0) {
return nullptr;
}
}
PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
if (item) {
return nullptr;
}
// search for an object with this name
DocumentObject* obj = getDocumentPtr()->getObject(attr);
return (obj ? obj->getPyObject() : nullptr);
}
int DocumentPy::setCustomAttributes(const char* attr, PyObject*)
{
// Note: Here we want to return only a document object if its
// name matches 'attr'. However, it is possible to have an object
// with the same name as an attribute. If so, we return 0 as other-
// wise it wouldn't be possible to address this attribute any more.
// The object must then be addressed by the getObject() method directly.
App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
if (prop) {
return 0;
}
if (!this->ob_type->tp_dict) {
if (PyType_Ready(this->ob_type) < 0) {
return 0;
}
}
PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
if (item) {
return 0;
}
DocumentObject* obj = getDocumentPtr()->getObject(attr);
if (obj) {
std::stringstream str;
str << "'Document' object attribute '" << attr << "' must not be set this way" << std::ends;
PyErr_SetString(PyExc_RuntimeError, str.str().c_str());
return -1;
}
return 0;
}
PyObject* DocumentPy::getLinksTo(PyObject* args)
{
PyObject* pyobj = Py_None;
int options = 0;
short count = 0;
if (!PyArg_ParseTuple(args, "|Oih", &pyobj, &options, &count)) {
return nullptr;
}
PY_TRY
{
Base::PyTypeCheck(&pyobj,
&DocumentObjectPy::Type,
"Expect the first argument of type document object");
DocumentObject* obj = nullptr;
if (pyobj) {
obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
}
std::set<DocumentObject*> links;
getDocumentPtr()->getLinksTo(links, obj, options, count);
Py::Tuple ret(links.size());
int i = 0;
for (auto o : links) {
ret.setItem(i++, Py::Object(o->getPyObject(), true));
}
return Py::new_reference_to(ret);
}
PY_CATCH
}
Py::List DocumentPy::getInList() const
{
Py::List ret;
auto lists = PropertyXLink::getDocumentInList(getDocumentPtr());
if (lists.size() == 1) {
for (auto doc : lists.begin()->second) {
ret.append(Py::Object(doc->getPyObject(), true));
}
}
return ret;
}
Py::List DocumentPy::getOutList() const
{
Py::List ret;
auto lists = PropertyXLink::getDocumentOutList(getDocumentPtr());
if (lists.size() == 1) {
for (auto doc : lists.begin()->second) {
ret.append(Py::Object(doc->getPyObject(), true));
}
}
return ret;
}
PyObject* DocumentPy::getDependentDocuments(PyObject* args)
{
PyObject* sort = Py_True;
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) {
return nullptr;
}
PY_TRY
{
auto docs = getDocumentPtr()->getDependentDocuments(Base::asBoolean(sort));
Py::List ret;
for (auto doc : docs) {
ret.append(Py::Object(doc->getPyObject(), true));
}
return Py::new_reference_to(ret);
}
PY_CATCH;
}
Py::Boolean DocumentPy::getRestoring() const
{
return {getDocumentPtr()->testStatus(Document::Status::Restoring)};
}
Py::Boolean DocumentPy::getPartial() const
{
return {getDocumentPtr()->testStatus(Document::Status::PartialDoc)};
}
Py::Boolean DocumentPy::getImporting() const
{
return {getDocumentPtr()->testStatus(Document::Status::Importing)};
}
Py::Boolean DocumentPy::getRecomputing() const
{
return {getDocumentPtr()->testStatus(Document::Status::Recomputing)};
}
Py::Boolean DocumentPy::getTransacting() const
{
return {getDocumentPtr()->isPerformingTransaction()};
}
Py::String DocumentPy::getOldLabel() const
{
return {getDocumentPtr()->getOldLabel()};
}
Py::Boolean DocumentPy::getTemporary() const
{
return {getDocumentPtr()->testStatus(Document::TempDoc)};
}