void NodeProxy::setAttr(std::string name, object obj) { if (!settable) throw proxy::ProxyException("Cannot set datum value."); Datum* datum = node->getDatum(QString::fromStdString(name)); if (!datum) throw proxy::ProxyException("Nonexistent datum lookup."); if (obj.ptr()->ob_type != datum->getType()) throw proxy::ProxyException("Invalid type."); auto e = dynamic_cast<EvalDatum*>(datum); if (!e) throw proxy::ProxyException("Datum must be an EvalDatum"); // Make sure that the existing expression can be directly coerced into // a value of the desired type. This is so that assigning x when // x equals "12.0" works, but assigning x when x = "po.y" fails. auto o = PyObject_CallFunction((PyObject*)datum->getType(), "s", e->getExpr().toStdString().c_str()); if (!o) { PyErr_Clear(); return; } Py_DECREF(o); auto txt = QString::fromStdString(extract<std::string>(str(obj))()); // Special case: use QString::number to sanely trim the number of decimal // places that are printed for float values. if (datum->getType() == &PyFloat_Type) txt = QString::number(txt.toFloat()); e->setExpr(txt); }