Fix the automated code generation for double and bool properties by marvinoe21 · Pull Request #573 · dlr-gtlab/python-module · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
6 changes: 5 additions & 1 deletion src/module/utilities/gtpy_calculatorfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ GtpyCalculatorFactory::createCalculator(const QString& className,
calc->moveToThread(parent->thread());
}

parent->appendChild(calc);
// ensure appendChild is called in the thread where parent and calc are
// living to avoid thread affinity issues
QMetaObject::invokeMethod(parent, [parent, calc](){
parent->appendChild(calc);
}, Qt::BlockingQueuedConnection);
}

// cppcheck-suppress unknownMacro
Expand Down
153 changes: 56 additions & 97 deletions src/module/utilities/gtpy_codegenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
*/

#include <QMetaProperty>
#include <QRegularExpression>

#include "gt_application.h"
#include "gt_calculator.h"
#include "gt_objectmementodiff.h"
#include "gt_datamodel.h"
#include "gt_package.h"
#include "gt_stringproperty.h"
#include "gt_modeproperty.h"
#include "gt_objectlinkproperty.h"
#include "gt_calculatorfactory.h"
#include "gt_calculatorhelperfactory.h"
Expand All @@ -25,6 +25,16 @@

#include "gtpy_codegenerator.h"

namespace {

inline QString quot(const QString& val)
{
return QString{"\"%1\""}.arg(val);
}

}


GtpyCodeGenerator::GtpyCodeGenerator(QObject* parent) : QObject(parent)
{

Expand Down Expand Up @@ -185,113 +195,28 @@ GtpyCodeGenerator::calculatorPyCode(GtCalculator* calc)
QString
GtpyCodeGenerator::propValToString(GtAbstractProperty* prop)
{
QString val;
QString val{};

if (qobject_cast<GtModeProperty*>(prop))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to the modeproperty cast?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the mode property is of type GtProperty<QString> it is handled in line 212.

if (qobject_cast<GtObjectLinkProperty*>(prop))
{
QString valTemp = GtpyContextManager::instance()->qvariantToPyStr(
prop->valueToVariant());

if (valTemp.isEmpty())
{
valTemp = "\"\"";
}

val = "\""
+ valTemp
+ "\"";
}
else if (qobject_cast<GtObjectLinkProperty*>(prop))
{
GtObject* obj = gtDataModel->objectByUuid(prop->valueToVariant().
toString());

if (obj)
{
GtPackage* pack = nullptr;

while (pack == nullptr)
{
QString objName = obj->objectName();

if (!objName.contains(
QRegExp(QStringLiteral("^[a-zA-Z0-9_]*$"))))
{
QString funcName =
GtpyContextManager::instance()->findChildFuncName();

objName = funcName + "(\"" + objName +
"\")";
}

obj = qobject_cast<GtObject*>(obj->parent());

if (obj == nullptr)
{
break;
}

pack = qobject_cast<GtPackage*>(obj);

val.insert(0, objName);

val.insert(0, ".");

if (pack != nullptr)
{
objName = pack->objectName();
const auto& uuid = prop->valueToVariant().toString();
val = pythonObjectPath(gtDataModel->objectByUuid(uuid));

if (!objName.contains(
QRegExp(QStringLiteral("^[a-zA-Z0-9_]*$"))))
{
QString funcName =
GtpyContextManager::instance()->
findChildFuncName();

objName = funcName + "(\"" + objName +
"\")";
}

val.insert(0, objName);
}
}

obj = nullptr;
pack = nullptr;
}
else
if (val.isEmpty())
{
QString valTemp = prop->valueToVariant().toString();

if (valTemp.isEmpty())
{
val = "\"\"";
}
else
{
val = GtpyContextManager::instance()->qvariantToPyStr(
prop->valueToVariant());
}
val = quot(uuid);
}
}
else if (qobject_cast<GtStringProperty*>(prop))
{
val = "\"";
val += GtpyContextManager::instance()->qvariantToPyStr(
prop->valueToVariant());
val += "\"";
}
else if (dynamic_cast<GtProperty<QString>*>(prop))
else if (qobject_cast<GtStringProperty*>(prop) ||
dynamic_cast<GtProperty<QString>*>(prop))
{
val = "\"";
val += GtpyContextManager::instance()->qvariantToPyStr(
prop->valueToVariant());
val += "\"";
val = quot(GtpyContextManager::instance()->qvariantToPyStr(
prop->valueToVariant()));
}
else
{
val = GtpyContextManager::instance()->qvariantToPyStr(
prop->valueToVariant());
prop->valueToVariant());
}

return val;
Expand Down Expand Up @@ -437,3 +362,37 @@ GtpyCodeGenerator::helperPyCode(GtObject* obj, const QString& pyObjName)

return pyCode;
}

QString
GtpyCodeGenerator::pythonObjectPath(GtObject* obj) const
{
QStringList objPath{};
generatePythonObjectPath(obj, objPath);
return objPath.join('.');
}

void
GtpyCodeGenerator::generatePythonObjectPath(GtObject* obj,
QStringList& objPath) const
{
if (!obj) return;

QString objGetter = obj->objectName();

// if the object name contains special characters use findGtChild
// with the object name as a parameter to get the object
if (!objGetter.contains(QRegularExpression("^[a-zA-Z0-9_]*$")))
{
objGetter = GtpyContextManager::instance()->findChildFuncName() +
"(" + quot(obj->objectName()) + ")";
}

objPath.prepend(objGetter);

// since packages are accessible directly via the Python context
// terminate recursion after resolving the package getter
if (qobject_cast<GtPackage*>(obj)) return;

generatePythonObjectPath(obj->parentObject(), objPath);
}

35 changes: 32 additions & 3 deletions src/module/utilities/gtpy_codegenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@
#ifndef GTPY_CODEGENERATOR_H
#define GTPY_CODEGENERATOR_H

#include <QObject>
#include "gt_pythonmodule_exports.h"

#include "gt_objectmemento.h"
#include <QObject>

class GtObject;
class GtAbstractProperty;
class GtCalculator;

/**
* @brief The GtpyCodeGenerator class
*/
class GtpyCodeGenerator : public QObject
class GT_PYTHON_EXPORT GtpyCodeGenerator : public QObject
{
Q_OBJECT

Expand Down Expand Up @@ -64,6 +66,33 @@ class GtpyCodeGenerator : public QObject
* @return The generated python code as string value.
*/
QString helperPyCode(GtObject* obj, const QString& pyObjName);

/**
* @brief Returns the object path of the specified object as Python code.
* The object path can be used to access the object in Python. It begins
* with the GtPackage to which the object belongs.
* @param obj The GtObject for which to generate the Python object path.
* @return The object path of the specified object which can be used to
* access the corresponding object in Python.
*/
QString pythonObjectPath(GtObject* obj) const;

/**
* @brief Recursively generates the object path of the specified object.
* It prepends the Python getter method of the given object to the
* getterList and calls itself, passing the parent object of the given
* object. The recursion stops when a GtPackage object is passed and
* processed or when the given object is a nullptr.
*
* To use the object path in Python, join the entries of the getterList
* with '.'.
*
* @param obj The GtObject for which to generate the Python object path.
* @param getterList A reference to a QStringList that stores the getter
* methods representing the object path of the specified object in Python.
*/
void generatePythonObjectPath(GtObject* obj, QStringList& getterList) const;

};

#endif // GTPY_CODEGENERATOR_H
2 changes: 1 addition & 1 deletion src/module/utilities/gtpy_contextmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ QString
GtpyContextManager::qvariantToPyStr(const QVariant& val) const
{
GTPY_GIL_SCOPE
return PyPPString_AsQString(PyPPObject::fromQVariant(val));
return PyPPObject_AsQString(PyPPObject::fromQVariant(val));
}

QString
Expand Down
13 changes: 13 additions & 0 deletions src/module/utilities/gtpypp.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,19 @@ inline QString PyPPString_AsQString(const PyPPObject& obj)
return QString::fromUtf8(PyPPUnicode_AsUTF8(obj));
}

inline QString PyPPObject_AsQString(const PyPPObject& obj)
{
auto strObj = obj;

if (!PyPPUnicode_Check(strObj))
{
strObj = PyPPObject::NewRef(PyObject_Str(obj.get()));
}

return PyPPString_AsQString(strObj);
}


inline QVariant PyPPObject_AsQVariant(const PyPPObject& obj)
{
if (obj && PyPPObject_TypeCheck(obj, &GtpyExtendedWrapperModule::GtpyExtendedWrapper_Type))
Expand Down
1 change: 1 addition & 0 deletions tests/unittests/CMakeLists.txt
Loading