From fc4a5592d65207f5f64e2e94c35cbc43d2e6f42c Mon Sep 17 00:00:00 2001 From: Ken Museth Date: Fri, 27 Oct 2023 18:34:03 -0700 Subject: [PATCH] Cleanup several aspects of the Python bindings (copy of PR #1696) (#1696) Signed-off-by: Ken Museth --- openvdb/openvdb/python/pyGrid.h | 50 +-- openvdb/openvdb/python/pyGridBase.cc | 8 +- openvdb/openvdb/python/pyOpenVDBModule.cc | 72 --- openvdb/openvdb/python/pyTransform.cc | 19 +- openvdb/openvdb/python/pyTypeCasters.h | 516 ++++++++++++++++++---- openvdb/openvdb/python/pyutil.h | 12 +- 6 files changed, 462 insertions(+), 215 deletions(-) diff --git a/openvdb/openvdb/python/pyGrid.h b/openvdb/openvdb/python/pyGrid.h index 55d96c2622..9249eaf6d2 100644 --- a/openvdb/openvdb/python/pyGrid.h +++ b/openvdb/openvdb/python/pyGrid.h @@ -68,7 +68,7 @@ inline bool sharesWith(const GridType& grid, py::object other) { if (py::isinstance(other)) { - typename GridType::ConstPtr otherGrid = other.cast(); + typename GridType::ConstPtr otherGrid = py::cast(other); return (&otherGrid->tree() == &grid.tree()); } return false; @@ -893,7 +893,7 @@ applyMap(const char* methodName, GridType& grid, py::object funcObj) // Verify that the result is of type GridType::ValueType. try { - result.cast(); + py::cast(result); } catch (py::cast_error&) { std::ostringstream os; os << "expected callable argument to "; @@ -904,7 +904,7 @@ applyMap(const char* methodName, GridType& grid, py::object funcObj) throw py::type_error(os.str()); } - it.setValue(result.cast()); + it.setValue(py::cast(result)); } } @@ -955,7 +955,7 @@ struct TreeCombineOp throw py::type_error(os.str()); } - result = resultObj.cast(); + result = py::cast(resultObj); } py::function op; }; @@ -1177,7 +1177,7 @@ class IterValueProxy py::object getItem(py::object keyObj) const { if (py::isinstance(keyObj)) { - const std::string key = keyObj.cast(); + const std::string key = py::cast(keyObj); if (key == "value") return py::cast(this->getValue()); else if (key == "active") return py::cast(this->getActive()); else if (key == "depth") return py::cast(this->getDepth()); @@ -1185,7 +1185,7 @@ class IterValueProxy else if (key == "max") return py::cast(this->getBBoxMax()); else if (key == "count") return py::cast(this->getVoxelCount()); } - throw py::key_error(keyObj.attr("__repr__")().cast()); + throw py::key_error(py::cast(keyObj.attr("__repr__")())); return py::object(); } @@ -1195,20 +1195,20 @@ class IterValueProxy void setItem(py::object keyObj, py::object valObj) { if (py::isinstance(keyObj)) { - const std::string key = keyObj.cast(); + const std::string key = py::cast(keyObj); if (key == "value") { - this->setValue(valObj.cast()); return; + this->setValue(py::cast(valObj)); return; } else if (key == "active") { - this->setActive(valObj.cast()); return; + this->setActive(py::cast(valObj)); return; } else if (this->hasKey(key)) { std::ostringstream os; os << "can't set attribute '"; - os << keyObj.attr("__repr__")().cast(); + os << py::cast(keyObj.attr("__repr__")()); os << "'"; throw py::attribute_error(os.str()); } } - throw py::key_error(keyObj.attr("__repr__")().cast()); + throw py::key_error(py::cast(keyObj.attr("__repr__")())); } bool operator==(const IterValueProxy& other) const @@ -1235,7 +1235,7 @@ class IterValueProxy } // print ", ".join(valuesAsStrings) py::object joined = py::str(", ").attr("join")(valuesAsStrings); - std::string s = joined.cast(); + std::string s = py::cast(joined); os << "{" << s << "}"; return os; } @@ -1379,13 +1379,9 @@ struct PickleSuite } // Construct a state tuple for the serialized Grid. -#if PY_MAJOR_VERSION >= 3 // Convert the byte string to a "bytes" sequence. const std::string s = ostr.str(); py::bytes bytesObj(s); -#else - py::str bytesObj(ostr.str()); -#endif return py::make_tuple(bytesObj); } @@ -1397,25 +1393,16 @@ struct PickleSuite std::string serialized; if (!badState) { // Extract the sequence containing the serialized Grid. -#if PY_MAJOR_VERSION >= 3 if (py::isinstance(state[0])) - serialized = state[0].cast(); -#else - if (py::isinstance(state[0])) - serialized = state[0].cast(); -#endif + serialized = py::cast(state[0]); else badState = true; } if (badState) { std::ostringstream os; -#if PY_MAJOR_VERSION >= 3 os << "expected (dict, bytes) tuple in call to __setstate__; found "; -#else - os << "expected (dict, str) tuple in call to __setstate__; found "; -#endif - os << state.attr("__repr__")().cast(); + os << py::cast(state.attr("__repr__")()); throw py::value_error(os.str()); } @@ -1457,14 +1444,15 @@ exportGrid(py::module_ m) using ValueAllIterT = typename GridType::ValueAllIter; const std::string pyGridTypeName = Traits::name(); - const std::string defaultCtorDescr = "Initialize with a background value of " - + pyutil::str(pyGrid::getZeroValue()) + "."; + std::stringstream docstream; + docstream << "Initialize with a background value of " << pyGrid::getZeroValue() << "."; + std::string docstring = docstream.str(); // Define the Grid wrapper class and make it the current scope. py::class_(m, /*classname=*/pyGridTypeName.c_str(), /*docstring=*/(Traits::descr()).c_str()) - .def(py::init<>(), defaultCtorDescr.c_str()) + .def(py::init<>(), docstring.c_str()) .def(py::init(), py::arg("background"), "Initialize with the given background value.") @@ -1711,7 +1699,7 @@ exportGrid(py::module_ m) IterWrap::wrap(m); // Add the Python type object for this grid type to the module-level list. - m.attr("GridTypes").cast().append(m.attr(pyGridTypeName.c_str())); + py::cast(m.attr("GridTypes")).append(m.attr(pyGridTypeName.c_str())); } } // namespace pyGrid diff --git a/openvdb/openvdb/python/pyGridBase.cc b/openvdb/openvdb/python/pyGridBase.cc index 19fa054dc6..0e10a58381 100644 --- a/openvdb/openvdb/python/pyGridBase.cc +++ b/openvdb/openvdb/python/pyGridBase.cc @@ -100,12 +100,8 @@ exportGridBase(py::module_ m) auto getMetadataKeys = [](GridBase::ConstPtr grid) { -#if PY_MAJOR_VERSION >= 3 // Return an iterator over the "keys" view of a dict. return py::make_key_iterator(static_cast(*grid).beginMeta(), static_cast(*grid).endMeta()); -#else - return py::dict(py::cast(static_cast(*grid))).iterkeys(); -#endif }; @@ -118,7 +114,7 @@ exportGridBase(py::module_ m) MetaMap metamap; metamap.insertMeta(name, *metadata); // todo: Add/refactor out type_casters for each TypedMetadata from MetaMap's type_caster - return py::dict(py::cast(metamap))[py::str(name)].cast(); + return py::cast(py::dict(py::cast(metamap))[py::str(name)]); }; @@ -135,7 +131,7 @@ exportGridBase(py::module_ m) // todo: Add/refactor out type_casters for each TypedMetadata from MetaMap's type_caster py::dict dictObj; dictObj[py::str(name)] = value; - MetaMap metamap = dictObj.cast(); + MetaMap metamap = py::cast(dictObj); if (Metadata::Ptr metadata = metamap[name]) { grid->removeMeta(name); diff --git a/openvdb/openvdb/python/pyOpenVDBModule.cc b/openvdb/openvdb/python/pyOpenVDBModule.cc index 37dd42287f..ed6754ac56 100644 --- a/openvdb/openvdb/python/pyOpenVDBModule.cc +++ b/openvdb/openvdb/python/pyOpenVDBModule.cc @@ -371,78 +371,6 @@ PYBIND11_MODULE(PY_OPENVDB_MODULE_NAME, m) #undef PYOPENVDB_TRANSLATE_EXCEPTION - // Basic bindings for these Vec types are required to support them as - // default arguments to functions. - py::class_(m, "Coord") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec2i") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec2f") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec2d") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec3i") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec3f") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec3d") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec4i") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec4f") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - - py::class_(m, "Vec4d") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::self == py::self) - .def(py::self != py::self); - py::class_(m, "PointDataIndex32") .def(py::init(), py::arg("i") = openvdb::Index32(0)); diff --git a/openvdb/openvdb/python/pyTransform.cc b/openvdb/openvdb/python/pyTransform.cc index c335e60dcf..b5116dfaef 100644 --- a/openvdb/openvdb/python/pyTransform.cc +++ b/openvdb/openvdb/python/pyTransform.cc @@ -99,12 +99,8 @@ struct PickleSuite // Construct a state tuple comprising the version numbers of // the serialization format and the serialized Transform. -#if PY_MAJOR_VERSION >= 3 // Convert the byte string to a "bytes" sequence. py::bytes bytesObj(ostr.str()); -#else - py::str bytesObj(ostr.str()); -#endif return py::make_tuple( uint32_t(OPENVDB_LIBRARY_MAJOR_VERSION), uint32_t(OPENVDB_LIBRARY_MINOR_VERSION), @@ -125,7 +121,7 @@ struct PickleSuite uint32_t version[3] = { 0, 0, 0 }; for (int i = 0; i < 3 && !badState; ++i) { if (py::isinstance(state[idx[i]])) - version[i] = state[idx[i]].cast(); + version[i] = py::cast(state[idx[i]]); else badState = true; } libVersion.first = version[0]; @@ -137,24 +133,15 @@ struct PickleSuite if (!badState) { // Extract the sequence containing the serialized Transform. py::object bytesObj = state[int(STATE_XFORM)]; -#if PY_MAJOR_VERSION >= 3 if (py::isinstance(bytesObj)) - serialized = bytesObj.cast(); -#else - if (py::isinstance(bytesObj)) - serialized = bytesObj.cast(); -#endif + serialized = py::cast(bytesObj); else badState = true; } if (badState) { std::ostringstream os; -#if PY_MAJOR_VERSION >= 3 os << "expected (int, int, int, bytes) tuple in call to __setstate__; found "; -#else - os << "expected (int, int, int, str) tuple in call to __setstate__; found "; -#endif - os << state.attr("__repr__")().cast(); + os << py::cast(state.attr("__repr__")()); throw py::value_error(os.str()); } diff --git a/openvdb/openvdb/python/pyTypeCasters.h b/openvdb/openvdb/python/pyTypeCasters.h index ea176b4f96..b30af05c6a 100644 --- a/openvdb/openvdb/python/pyTypeCasters.h +++ b/openvdb/openvdb/python/pyTypeCasters.h @@ -633,11 +633,7 @@ namespace pybind11 { namespace detail { PyObject* source = src.ptr(); PyObject* number = PyNumber_Long(source); if (number) { -#if PY_MAJOR_VERSION >= 3 value = static_cast(PyLong_AsLong(number)); -#else - value = static_cast(PyInt_AsLong(number)); -#endif } Py_XDECREF(number); @@ -661,11 +657,7 @@ namespace pybind11 { namespace detail { PyObject* source = src.ptr(); PyObject* number = PyNumber_Long(source); if (number) { -#if PY_MAJOR_VERSION >= 3 value = static_cast(PyLong_AsLong(number)); -#else - value = static_cast(PyInt_AsLong(number)); -#endif } Py_XDECREF(number); @@ -681,44 +673,393 @@ namespace pybind11 { namespace detail { } }; - template <> struct type_caster { + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::PointDataIndex32, const_name("openvdb::PointDataIndex32")); + + bool load(handle src, bool) { + PyObject* source = src.ptr(); + PyObject* number = PyNumber_Long(source); + if (number) { + value = static_cast(PyLong_AsLong(number)); + } + Py_XDECREF(number); + + if (PyErr_Occurred()) + return false; + + return true; + } + + static handle cast(openvdb::PointDataIndex32 src, return_value_policy, handle) { + py::int_ integer(static_cast(src)); + return integer.release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::PointDataIndex64, const_name("openvdb::PointDataIndex64")); + + bool load(handle src, bool) { + PyObject* source = src.ptr(); + PyObject* number = PyNumber_Long(source); + if (number) { + value = static_cast(PyLong_AsLong(number)); + } + Py_XDECREF(number); + + if (PyErr_Occurred()) + return false; + + return true; + } + + static handle cast(openvdb::PointDataIndex64 src, return_value_policy, handle) { + py::int_ integer(static_cast(src)); + return integer.release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::StringMetadata, _("openvdb::StringMetadata")); + + bool load(handle src, bool) { + if (!py::isinstance(src)) { + return false; + } + + value.setValue(py::cast(src)); + return true; + } + + static handle cast(openvdb::StringMetadata src, return_value_policy, handle) { + return py::str(src.value()).release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::BoolMetadata, _("openvdb::BoolMetadata")); + + bool load(handle src, bool) { + if (!py::isinstance(src)) { + return false; + } + + value.setValue(py::cast(src)); + return true; + } + + static handle cast(openvdb::BoolMetadata src, return_value_policy, handle) { + return py::bool_(src.value()).release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Int32Metadata, _("openvdb::Int32Metadata")); + + bool load(handle src, bool) { + if (!py::isinstance(src)) { + return false; + } + + value.setValue(py::cast(src)); + return true; + } + + static handle cast(openvdb::Int32Metadata src, return_value_policy, handle) { + return py::int_(src.value()).release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Int64Metadata, _("openvdb::Int64Metadata")); + + bool load(handle src, bool) { + if (!py::isinstance(src)) { + return false; + } + + value.setValue(py::cast(src)); + return true; + } + + static handle cast(openvdb::Int64Metadata src, return_value_policy, handle) { + return py::int_(src.value()).release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::FloatMetadata, _("openvdb::FloatMetadata")); + + bool load(handle src, bool) { + if (!py::isinstance(src)) { + return false; + } + + value.setValue(py::cast(src)); + return true; + } + + static handle cast(openvdb::FloatMetadata src, return_value_policy, handle) { + return py::float_(src.value()).release(); + } + }; + + template <> struct type_caster { public: - PYBIND11_TYPE_CASTER(openvdb::MetaMap, _("openvdb::Metamap")); + PYBIND11_TYPE_CASTER(openvdb::DoubleMetadata, _("openvdb::DoubleMetadata")); bool load(handle src, bool) { + if (!py::isinstance(src)) { + return false; + } + + value.setValue(py::cast(src)); + return true; + } + + static handle cast(openvdb::DoubleMetadata src, return_value_policy, handle) { + return py::float_(src.value()).release(); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Vec2IMetadata, _("openvdb::Vec2IMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Vec2IMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Vec3IMetadata, _("openvdb::Vec3IMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Vec3IMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Vec4IMetadata, _("openvdb::Vec4IMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Vec4IMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Vec2DMetadata, _("openvdb::Vec2DMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Vec2DMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Vec3DMetadata, _("openvdb::Vec3DMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Vec3DMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Vec4DMetadata, _("openvdb::Vec4DMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Vec4DMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Mat4SMetadata, _("openvdb::Mat4SMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Mat4SMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::Mat4DMetadata, _("openvdb::Mat4DMetadata")); + + bool load(handle src, bool convert) { + if (!py::isinstance(src)) { + return false; + } + + make_caster conv; + if (!conv.load(src, convert)) + return false; + + value.setValue(cast_op(std::move(conv))); + return true; + } + + static handle cast(openvdb::Mat4DMetadata src, return_value_policy policy, handle parent) { + return make_caster::cast(src.value(), policy, parent); + } + }; + + template <> struct type_caster { + public: + PYBIND11_TYPE_CASTER(openvdb::MetaMap, _("openvdb::MetaMap")); + + bool load(handle src, bool convert) { py::dict dictionary = py::reinterpret_borrow(src); - for (auto item : dictionary) { + for (auto [key, val] : dictionary) { std::string name; - py::object key = py::reinterpret_borrow(item.first); if (py::isinstance(key)) { - name = key.cast(); + name = py::cast(key); } else { throw py::type_error("Expected string as metadata name"); } - openvdb::Metadata::Ptr metadata; // Note: the order of the following tests is significant, as it // avoids unnecessary type promotion (e.g., of ints to doubles). // Python does not natively support single precision and therefore // all floating point metadata is promoted to doubles. - py::object val = py::reinterpret_borrow(item.second); + bool success = false; if (py::isinstance(val)) { - metadata.reset(new openvdb::StringMetadata(val.cast())); + make_caster conv; + if(conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } } else if (py::isinstance(val)) { - metadata.reset(new openvdb::BoolMetadata(val.cast())); + make_caster conv; + if(conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } } else if (py::isinstance(val)) { - const openvdb::Int64 n = val.cast(); - if (n <= std::numeric_limits::max() - && n >= std::numeric_limits::min()) { - metadata.reset(new openvdb::Int32Metadata(static_cast(n))); + const openvdb::Int64 n = py::cast(val); + if (n <= std::numeric_limits::max() && n >= std::numeric_limits::min()) { + make_caster conv; + if(conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } } else { - metadata.reset(new openvdb::Int64Metadata(n)); + make_caster conv; + if(conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } } } else if (py::isinstance(val)) { - metadata.reset(new openvdb::DoubleMetadata(val.cast())); + make_caster conv; + if(conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } } else if (py::isinstance(val)) { - py::tuple t = val.cast(); + py::tuple t = py::cast(val); size_t size = t.size(); bool isIntegerTuple = true; for (size_t i = 0; i < size; ++i) { @@ -727,110 +1068,127 @@ namespace pybind11 { namespace detail { if (isIntegerTuple) { switch(size) { - case 2: - metadata.reset(new openvdb::Vec2IMetadata(t.cast())); + case 2: { + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } break; - case 3: - metadata.reset(new openvdb::Vec3IMetadata(t.cast())); + } + case 3: { + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } break; - case 4: - metadata.reset(new openvdb::Vec4IMetadata(t.cast())); + } + case 4: { + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } break; + } default: break; } } else { switch(size) { - case 2: - metadata.reset(new openvdb::Vec2DMetadata(t.cast())); + case 2: { + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } break; - case 3: - metadata.reset(new openvdb::Vec3DMetadata(t.cast())); + } + case 3: { + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } break; - case 4: - metadata.reset(new openvdb::Vec4DMetadata(t.cast())); + } + case 4: { + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; + } break; + } default: break; } } } else if (py::isinstance(val)) { - py::list list = val.cast(); - bool valid = (list.size() == 4); - if (valid) { - for (size_t i = 0; i < list.size(); ++i) { - valid &= py::isinstance(list[i]); - if (valid) { - py::list sublist = list[i].cast(); - valid &= (sublist.size() == 4); - if (valid) { - for (size_t j = 0; j < sublist.size(); ++j) { - valid &= (py::isinstance(sublist[j]) || py::isinstance(sublist[j])); - } - } - } - } - } - if (valid) { - metadata.reset(new openvdb::Mat4DMetadata(val.cast())); + make_caster conv; + if (conv.load(val, convert)) { + value.insertMeta(name, cast_op(std::move(conv))); + success = true; } } else if (py::isinstance(val)) { - metadata = val.cast(); + openvdb::Metadata::Ptr metadata = py::cast(val); + if (metadata) { + value.insertMeta(name, *metadata); + } + } - if (metadata) { - value.insertMeta(name, *metadata); - } else { - const std::string valAsStr = (val.attr("__str__")()).cast(); - const std::string valType = val.attr("__class__").attr("__name__").cast(); + if (!success) { + const std::string valAsStr = py::cast(val.attr("__str__")()); + const std::string valType = py::cast(val.attr("__class__").attr("__name__")); throw py::type_error(std::string("metadata value " + valAsStr + " of type " + valType + " is not allowed")); } - } return true; } - static handle cast(openvdb::MetaMap src, return_value_policy, handle) { + static handle cast(openvdb::MetaMap src, return_value_policy policy, handle parent) { py::dict dict; for (openvdb::MetaMap::ConstMetaIterator it = src.beginMeta(); it != src.endMeta(); ++it) { if (openvdb::Metadata::Ptr meta = it->second) { py::object obj(py::cast(meta)); const std::string typeName = meta->typeName(); if (typeName == openvdb::StringMetadata::staticTypeName()) { - obj = py::str(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::DoubleMetadata::staticTypeName()) { - obj = py::float_(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::FloatMetadata::staticTypeName()) { - obj = py::float_(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Int32Metadata::staticTypeName()) { - obj = py::int_(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Int64Metadata::staticTypeName()) { - obj = py::int_(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::BoolMetadata::staticTypeName()) { - obj = py::bool_(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec2DMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec2IMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec2SMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec3DMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec3IMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec3SMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec4DMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec4IMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Vec4SMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Mat4SMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } else if (typeName == openvdb::Mat4DMetadata::staticTypeName()) { - obj = py::cast(static_cast(*meta).value()); + obj = reinterpret_steal(make_caster::cast(static_cast(*meta), policy, parent)); } dict[py::str(it->first)] = obj; } diff --git a/openvdb/openvdb/python/pyutil.h b/openvdb/openvdb/python/pyutil.h index 52216666cc..1727e0aace 100644 --- a/openvdb/openvdb/python/pyutil.h +++ b/openvdb/openvdb/python/pyutil.h @@ -163,21 +163,11 @@ struct StringEnum //////////////////////////////////////// - -/// Return str(val) for the given value. -template -inline std::string -str(const T& val) -{ - return py::str(py::cast(val)); -} - - /// Return the name of the given Python object's class. inline std::string className(py::handle h) { - return h.attr("__class__").attr("__name__").cast(); + return py::cast(h.attr("__class__").attr("__name__")); } } // namespace pyutil