From 06e7e57217fe5fae3f29d9f41b19222cde4e4ab1 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sun, 20 Mar 2022 23:58:21 +0100 Subject: [PATCH 01/13] Added bindings and changes required for dai::Path --- src/CalibrationHandlerBindings.cpp | 4 +-- src/DeviceBindings.cpp | 32 ++++++++++++------------ src/DeviceBootloaderBindings.cpp | 14 +++++------ src/openvino/OpenVINOBindings.cpp | 2 +- src/pipeline/AssetManagerBindings.cpp | 4 +-- src/pipeline/NodeBindings.cpp | 10 ++++---- src/pybind11_common.hpp | 36 +++++++++++++++++++++++++++ 7 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/CalibrationHandlerBindings.cpp b/src/CalibrationHandlerBindings.cpp index e4a018b12..25443f349 100644 --- a/src/CalibrationHandlerBindings.cpp +++ b/src/CalibrationHandlerBindings.cpp @@ -25,8 +25,8 @@ void CalibrationHandlerBindings::bind(pybind11::module& m, void* pCallstack){ // Bindings calibrationHandler .def(py::init<>(), DOC(dai, CalibrationHandler, CalibrationHandler)) - .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 2)) - .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 3)) + .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 2)) + .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 3)) .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 4)) .def("getEepromData", &CalibrationHandler::getEepromData, DOC(dai, CalibrationHandler, getEepromData)) diff --git a/src/DeviceBindings.cpp b/src/DeviceBindings.cpp index 6a2981988..02bd67f75 100644 --- a/src/DeviceBindings.cpp +++ b/src/DeviceBindings.cpp @@ -115,7 +115,7 @@ static void bindConstructors(ARG& arg){ py::gil_scoped_release release; return std::make_unique(pipeline, dev, maxUsbSpeed); }), py::arg("pipeline"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 3)) - .def(py::init([](const Pipeline& pipeline, const std::string& pathToCmd){ + .def(py::init([](const Pipeline& pipeline, const dai::Path& pathToCmd){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(pipeline, dev, pathToCmd); @@ -123,58 +123,58 @@ static void bindConstructors(ARG& arg){ .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, bool usb2Mode){ py::gil_scoped_release release; return std::make_unique(pipeline, deviceInfo, usb2Mode); - }), py::arg("pipeline"), py::arg("devInfo"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 7)) + }), py::arg("pipeline"), py::arg("devInfo"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 6)) .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, UsbSpeed maxUsbSpeed){ py::gil_scoped_release release; return std::make_unique(pipeline, deviceInfo, maxUsbSpeed); - }), py::arg("pipeline"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 8)) - .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, std::string pathToCmd){ + }), py::arg("pipeline"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 7)) + .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, dai::Path pathToCmd){ py::gil_scoped_release release; return std::make_unique(pipeline, deviceInfo, pathToCmd); - }), py::arg("pipeline"), py::arg("devInfo"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 9)) + }), py::arg("pipeline"), py::arg("devInfo"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 8)) // DeviceBase constructor - OpenVINO version .def(py::init([](OpenVINO::Version version){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev); - }), py::arg("version") = OpenVINO::DEFAULT_VERSION, DOC(dai, DeviceBase, DeviceBase, 11)) + }), py::arg("version") = OpenVINO::DEFAULT_VERSION, DOC(dai, DeviceBase, DeviceBase, 10)) .def(py::init([](OpenVINO::Version version, bool usb2Mode){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev, usb2Mode); - }), py::arg("version"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 13)) + }), py::arg("version"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 11)) .def(py::init([](OpenVINO::Version version, UsbSpeed maxUsbSpeed){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev, maxUsbSpeed); - }), py::arg("version"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 14)) - .def(py::init([](OpenVINO::Version version, const std::string& pathToCmd){ + }), py::arg("version"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 12)) + .def(py::init([](OpenVINO::Version version, const dai::Path& pathToCmd){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev, pathToCmd); - }), py::arg("version"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 15)) + }), py::arg("version"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 13)) .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, bool usb2Mode){ py::gil_scoped_release release; return std::make_unique(version, deviceInfo, usb2Mode); - }), py::arg("version"), py::arg("deviceDesc"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 18)) + }), py::arg("version"), py::arg("deviceDesc"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 15)) .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, UsbSpeed maxUsbSpeed){ py::gil_scoped_release release; return std::make_unique(version, deviceInfo, maxUsbSpeed); - }), py::arg("version"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 19)) - .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, std::string pathToCmd){ + }), py::arg("version"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 16)) + .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, dai::Path pathToCmd){ py::gil_scoped_release release; return std::make_unique(version, deviceInfo, pathToCmd); - }), py::arg("version"), py::arg("deviceDesc"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 20)) + }), py::arg("version"), py::arg("deviceDesc"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 17)) .def(py::init([](typename D::Config config){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(config, dev); - }), py::arg("config"), DOC(dai, DeviceBase, DeviceBase, 22)) + }), py::arg("config"), DOC(dai, DeviceBase, DeviceBase, 18)) .def(py::init([](typename D::Config config, const DeviceInfo& deviceInfo){ py::gil_scoped_release release; return std::make_unique(config, deviceInfo); - }), py::arg("config"), py::arg("deviceInfo"), DOC(dai, DeviceBase, DeviceBase, 23)) + }), py::arg("config"), py::arg("deviceInfo"), DOC(dai, DeviceBase, DeviceBase, 19)) ; } diff --git a/src/DeviceBootloaderBindings.cpp b/src/DeviceBootloaderBindings.cpp index 81b2a37d9..b3ab5d59e 100644 --- a/src/DeviceBootloaderBindings.cpp +++ b/src/DeviceBootloaderBindings.cpp @@ -116,25 +116,25 @@ void DeviceBootloaderBindings::bind(pybind11::module& m, void* pCallstack){ .def_static("getFirstAvailableDevice", &DeviceBootloader::getFirstAvailableDevice, DOC(dai, DeviceBootloader, getFirstAvailableDevice)) .def_static("getAllAvailableDevices", &DeviceBootloader::getAllAvailableDevices, DOC(dai, DeviceBootloader, getAllAvailableDevices)) - .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("pathToCmd") = "", py::arg("compress") = false, DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage)) - .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("compress"), DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage, 2)) - .def_static("createDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::createDepthaiApplicationPackage), py::arg("pipeline"), py::arg("pathToCmd") = "", py::arg("compress") = false, DOC(dai, DeviceBootloader, createDepthaiApplicationPackage)) + .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("pathToCmd") = Path{}, py::arg("compress") = false, DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage)) + .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("compress"), DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage, 2)) + .def_static("createDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::createDepthaiApplicationPackage), py::arg("pipeline"), py::arg("pathToCmd") = Path{}, py::arg("compress") = false, DOC(dai, DeviceBootloader, createDepthaiApplicationPackage)) .def_static("createDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::createDepthaiApplicationPackage), py::arg("pipeline"), py::arg("compress"), DOC(dai, DeviceBootloader, createDepthaiApplicationPackage, 2)) .def_static("getEmbeddedBootloaderVersion", &DeviceBootloader::getEmbeddedBootloaderVersion, DOC(dai, DeviceBootloader, getEmbeddedBootloaderVersion)) .def_static("getEmbeddedBootloaderBinary", &DeviceBootloader::getEmbeddedBootloaderBinary, DOC(dai, DeviceBootloader, getEmbeddedBootloaderBinary)) .def(py::init(), py::arg("devInfo"), py::arg("allowFlashingBootloader") = false, DOC(dai, DeviceBootloader, DeviceBootloader)) - .def(py::init(), py::arg("devInfo"), py::arg("pathToCmd"), py::arg("allowFlashingBootloader") = false, DOC(dai, DeviceBootloader, DeviceBootloader, 2)) + .def(py::init(), py::arg("devInfo"), py::arg("pathToCmd"), py::arg("allowFlashingBootloader") = false, DOC(dai, DeviceBootloader, DeviceBootloader, 2)) .def("flash", [](DeviceBootloader& db, std::function progressCallback, const Pipeline& pipeline, bool compress) { py::gil_scoped_release release; return db.flash(progressCallback, pipeline, compress); }, py::arg("progressCallback"), py::arg("pipeline"), py::arg("compress") = false, DOC(dai, DeviceBootloader, flash)) .def("flash", [](DeviceBootloader& db, const Pipeline& pipeline, bool compress) { py::gil_scoped_release release; return db.flash(pipeline, compress); }, py::arg("pipeline"), py::arg("compress") = false, DOC(dai, DeviceBootloader, flash, 2)) .def("flashDepthaiApplicationPackage", [](DeviceBootloader& db, std::function progressCallback, std::vector package) { py::gil_scoped_release release; return db.flashDepthaiApplicationPackage(progressCallback, package); }, py::arg("progressCallback"), py::arg("package"), DOC(dai, DeviceBootloader, flashDepthaiApplicationPackage)) .def("flashDepthaiApplicationPackage", [](DeviceBootloader& db, std::vector package) { py::gil_scoped_release release; return db.flashDepthaiApplicationPackage(package); }, py::arg("package"), DOC(dai, DeviceBootloader, flashDepthaiApplicationPackage, 2)) - .def("flashBootloader", [](DeviceBootloader& db, std::function progressCallback, std::string path) { py::gil_scoped_release release; return db.flashBootloader(progressCallback, path); }, py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader)) - .def("flashBootloader", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type, std::function progressCallback, std::string path) { py::gil_scoped_release release; return db.flashBootloader(memory, type, progressCallback, path); }, py::arg("memory"), py::arg("type"), py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader, 2)) + .def("flashBootloader", [](DeviceBootloader& db, std::function progressCallback, const Path& path) { py::gil_scoped_release release; return db.flashBootloader(progressCallback, path); }, py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader)) + .def("flashBootloader", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type, std::function progressCallback, dai::Path path) { py::gil_scoped_release release; return db.flashBootloader(memory, type, progressCallback, path); }, py::arg("memory"), py::arg("type"), py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader, 2)) .def("readConfigData", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.readConfigData(memory, type); }, py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, readConfigData)) .def("flashConfigData", [](DeviceBootloader& db, nlohmann::json configData, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigData(configData, memory, type); }, py::arg("configData"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigData)) - .def("flashConfigFile", [](DeviceBootloader& db, std::string configPath, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigFile(configPath, memory, type); }, py::arg("configData"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigFile)) + .def("flashConfigFile", [](DeviceBootloader& db, dai::Path configPath, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigFile(configPath, memory, type); }, py::arg("configData"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigFile)) .def("flashConfigClear", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigClear(memory, type); }, py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigClear)) .def("readConfig", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.readConfig(memory, type); }, py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, readConfig)) .def("flashConfig", [](DeviceBootloader& db, const DeviceBootloader::Config& config, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfig(config, memory, type); }, py::arg("config"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfig)) diff --git a/src/openvino/OpenVINOBindings.cpp b/src/openvino/OpenVINOBindings.cpp index f096f72ef..29cb6da94 100644 --- a/src/openvino/OpenVINOBindings.cpp +++ b/src/openvino/OpenVINOBindings.cpp @@ -57,7 +57,7 @@ void OpenVINOBindings::bind(pybind11::module& m, void* pCallstack){ // Bind OpenVINO::Blob openvinoBlob .def(py::init>(), DOC(dai, OpenVINO, Blob, Blob)) - .def(py::init(), DOC(dai, OpenVINO, Blob, Blob, 2)) + .def(py::init(), DOC(dai, OpenVINO, Blob, Blob, 2)) .def_readwrite("version", &OpenVINO::Blob::version, DOC(dai, OpenVINO, Blob, version)) .def_readwrite("networkInputs", &OpenVINO::Blob::networkInputs, DOC(dai, OpenVINO, Blob, networkInputs)) .def_readwrite("networkOutputs", &OpenVINO::Blob::networkOutputs, DOC(dai, OpenVINO, Blob, networkOutputs)) diff --git a/src/pipeline/AssetManagerBindings.cpp b/src/pipeline/AssetManagerBindings.cpp index 72b3b29f9..ac27e5ed3 100644 --- a/src/pipeline/AssetManagerBindings.cpp +++ b/src/pipeline/AssetManagerBindings.cpp @@ -30,7 +30,7 @@ void AssetManagerBindings::bind(pybind11::module& m, void* pCallstack){ // Bind Asset asset .def(py::init<>()) - .def(py::init()) + .def(py::init()) .def_readonly("key", &Asset::key) // numpy array access - zero copy on access .def_property("data", [](py::object &obj){ @@ -49,7 +49,7 @@ void AssetManagerBindings::bind(pybind11::module& m, void* pCallstack){ .def("addExisting", &AssetManager::addExisting, py::arg("assets"), DOC(dai, AssetManager, addExisting)) .def("set", static_cast (AssetManager::*)(Asset)>(&AssetManager::set), py::arg("asset"), DOC(dai, AssetManager, set)) .def("set", static_cast (AssetManager::*)(const std::string&, Asset)>(&AssetManager::set), py::arg("key"), py::arg("asset"), DOC(dai, AssetManager, set, 2)) - .def("set", static_cast (AssetManager::*)(const std::string& key, const std::string& path, int alignment)>(&AssetManager::set), py::arg("key"), py::arg("path"), py::arg("alignment") = 64, DOC(dai, AssetManager, set, 3)) + .def("set", static_cast (AssetManager::*)(const std::string& key, const dai::Path& path, int alignment)>(&AssetManager::set), py::arg("key"), py::arg("path"), py::arg("alignment") = 64, DOC(dai, AssetManager, set, 3)) .def("set", static_cast (AssetManager::*)(const std::string& key, const std::vector& data, int alignment)>(&AssetManager::set), py::arg("key"), py::arg("data"), py::arg("alignment") = 64, DOC(dai, AssetManager, set, 4)) .def("get", static_cast (AssetManager::*)(const std::string&) const>(&AssetManager::get), py::arg("key"), DOC(dai, AssetManager, get)) .def("get", static_cast (AssetManager::*)(const std::string&)>(&AssetManager::get), py::arg("key"), DOC(dai, AssetManager, get, 2)) diff --git a/src/pipeline/NodeBindings.cpp b/src/pipeline/NodeBindings.cpp index af5a11e39..ea6528561 100644 --- a/src/pipeline/NodeBindings.cpp +++ b/src/pipeline/NodeBindings.cpp @@ -216,7 +216,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ auto edgeDetector = ADD_NODE(EdgeDetector); auto featureTracker = ADD_NODE(FeatureTracker); auto aprilTag = ADD_NODE(AprilTag); - + py::enum_ stereoDepthPresetMode(stereoDepth, "PresetMode", DOC(dai, node, StereoDepth, PresetMode)); @@ -677,7 +677,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ .def_readonly("passthrough", &NeuralNetwork::passthrough, DOC(dai, node, NeuralNetwork, passthrough)) .def("setBlobPath", [](NeuralNetwork& nn, py::object obj){ // Allows to call this function with paths as well as strings - nn.setBlobPath(py::str(obj)); + nn.setBlobPath(dai::Path(py::str(obj))); }, py::arg("path"), DOC(dai, node, NeuralNetwork, setBlobPath)) .def("setNumPoolFrames", &NeuralNetwork::setNumPoolFrames, py::arg("numFrames"), DOC(dai, node, NeuralNetwork, setNumPoolFrames)) .def("setNumInferenceThreads", &NeuralNetwork::setNumInferenceThreads, py::arg("numThreads"), DOC(dai, node, NeuralNetwork, setNumInferenceThreads)) @@ -898,7 +898,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ s.setOutputDepth(enable); HEDLEY_DIAGNOSTIC_POP }) - .def("loadCalibrationFile", [](StereoDepth& s, std::string path){ + .def("loadCalibrationFile", [](StereoDepth& s, dai::Path path){ PyErr_WarnEx(PyExc_DeprecationWarning, "loadCalibrationFile() is deprecated, Use 'Pipeline.setCalibrationData()' instead", 1); HEDLEY_DIAGNOSTIC_PUSH HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED @@ -1224,8 +1224,8 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ .def_readonly("initialConfig", &AprilTag::initialConfig, DOC(dai, node, AprilTag, initialConfig)) .def("setWaitForConfigInput", &AprilTag::setWaitForConfigInput, py::arg("wait"), DOC(dai, node, AprilTag, setWaitForConfigInput)) ; - daiNodeModule.attr("AprilTag").attr("Properties") = aprilTagProperties; - + daiNodeModule.attr("AprilTag").attr("Properties") = aprilTagProperties; + // FeatureTracker node featureTracker .def_readonly("inputConfig", &FeatureTracker::inputConfig, DOC(dai, node, FeatureTracker, inputConfig)) diff --git a/src/pybind11_common.hpp b/src/pybind11_common.hpp index 1669cdf40..258859745 100644 --- a/src/pybind11_common.hpp +++ b/src/pybind11_common.hpp @@ -12,6 +12,7 @@ #include #include #include +#include // Include docstring file #include "docstring.hpp" @@ -24,6 +25,41 @@ namespace pybind11 { namespace detail { struct type_caster> : optional_caster> {}; }} + +namespace pybind11 { namespace detail { + template <> struct type_caster { + public: + + // This macro establishes the name 'dai::Path' in + // function signatures and declares a local variable + // 'value' of type dai::Path + PYBIND11_TYPE_CASTER(dai::Path, _("Path")); + + // Conversion part 1 (Python->C++): convert a PyObject into a dai::Path + // instance or return false upon failure. The second argument + // indicates whether implicit conversions should be applied. + bool load(handle src, bool) { + try { + str pystr = static_cast(src); + value = dai::Path(static_cast(pystr)); + return true; + } catch (...) { + return false; + } + } + + // Conversion part 2 (C++ -> Python): convert an dai::Path instance into + // a Python (string) object. The second and third arguments are used to + // indicate the return value policy and parent object (for + // ``return_value_policy::reference_internal``) and are generally + // ignored by implicit casters. + static handle cast(dai::Path src, return_value_policy /* policy */, handle /* parent */) { + return str{src.u8string()}; + } + }; +}} // namespace pybind11::detail + + namespace py = pybind11; using StackFunction = void (*)(pybind11::module &m, void *pCallstack); From faba6bbc5e9a2ba89105916286ce6d70eb31d17e Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Mon, 21 Mar 2022 00:23:43 +0100 Subject: [PATCH 02/13] Added a simple test for UTF-8 path support --- tests/CMakeLists.txt | 1 + tests/utf8_support_test.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/utf8_support_test.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3aad2e65..3c0eec650 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,7 @@ endif() set(PYBIND11_TEST_FILES "xlink_exceptions_test.cpp" + "utf8_support_test.py" ) string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}") diff --git a/tests/utf8_support_test.py b/tests/utf8_support_test.py new file mode 100644 index 000000000..01f3ca2b3 --- /dev/null +++ b/tests/utf8_support_test.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +import sys + +import pytest + +import depthai as dai + +def test_utf8_path_asset_manager(tmp_path): + + FILE_CONTENTS="Hello World πŸ‘" + + tmp_sneaky_file_dir = tmp_path / "UTF-8 dir πŸ™ˆπŸ™‰πŸ™‰" + tmp_sneaky_file_dir.mkdir() + tmp_sneaky_file_path = tmp_sneaky_file_dir / "sneaky πŸ‘ ΔΔ‡Ε‘Δ‘ΕΎΔ†ΔŒLpΔ‘Ε‘lčk file.txt" + tmp_sneaky_file_path.write_text(FILE_CONTENTS) + + assetManager = dai.AssetManager() + asset = assetManager.set('test', tmp_sneaky_file_path) + assert(bytes(asset.data) == FILE_CONTENTS.encode("utf-8")) From 2227200aa393e85610cea5e9c2981f8080cd2d08 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 11:52:46 +0200 Subject: [PATCH 03/13] Added bindings and changes required for dai::Path --- src/CalibrationHandlerBindings.cpp | 4 +-- src/DeviceBindings.cpp | 32 ++++++++++++------------ src/DeviceBootloaderBindings.cpp | 14 +++++------ src/openvino/OpenVINOBindings.cpp | 2 +- src/pipeline/AssetManagerBindings.cpp | 4 +-- src/pipeline/NodeBindings.cpp | 10 ++++---- src/pybind11_common.hpp | 36 +++++++++++++++++++++++++++ 7 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/CalibrationHandlerBindings.cpp b/src/CalibrationHandlerBindings.cpp index e4a018b12..25443f349 100644 --- a/src/CalibrationHandlerBindings.cpp +++ b/src/CalibrationHandlerBindings.cpp @@ -25,8 +25,8 @@ void CalibrationHandlerBindings::bind(pybind11::module& m, void* pCallstack){ // Bindings calibrationHandler .def(py::init<>(), DOC(dai, CalibrationHandler, CalibrationHandler)) - .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 2)) - .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 3)) + .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 2)) + .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 3)) .def(py::init(), DOC(dai, CalibrationHandler, CalibrationHandler, 4)) .def("getEepromData", &CalibrationHandler::getEepromData, DOC(dai, CalibrationHandler, getEepromData)) diff --git a/src/DeviceBindings.cpp b/src/DeviceBindings.cpp index 6a2981988..02bd67f75 100644 --- a/src/DeviceBindings.cpp +++ b/src/DeviceBindings.cpp @@ -115,7 +115,7 @@ static void bindConstructors(ARG& arg){ py::gil_scoped_release release; return std::make_unique(pipeline, dev, maxUsbSpeed); }), py::arg("pipeline"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 3)) - .def(py::init([](const Pipeline& pipeline, const std::string& pathToCmd){ + .def(py::init([](const Pipeline& pipeline, const dai::Path& pathToCmd){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(pipeline, dev, pathToCmd); @@ -123,58 +123,58 @@ static void bindConstructors(ARG& arg){ .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, bool usb2Mode){ py::gil_scoped_release release; return std::make_unique(pipeline, deviceInfo, usb2Mode); - }), py::arg("pipeline"), py::arg("devInfo"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 7)) + }), py::arg("pipeline"), py::arg("devInfo"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 6)) .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, UsbSpeed maxUsbSpeed){ py::gil_scoped_release release; return std::make_unique(pipeline, deviceInfo, maxUsbSpeed); - }), py::arg("pipeline"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 8)) - .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, std::string pathToCmd){ + }), py::arg("pipeline"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 7)) + .def(py::init([](const Pipeline& pipeline, const DeviceInfo& deviceInfo, dai::Path pathToCmd){ py::gil_scoped_release release; return std::make_unique(pipeline, deviceInfo, pathToCmd); - }), py::arg("pipeline"), py::arg("devInfo"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 9)) + }), py::arg("pipeline"), py::arg("devInfo"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 8)) // DeviceBase constructor - OpenVINO version .def(py::init([](OpenVINO::Version version){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev); - }), py::arg("version") = OpenVINO::DEFAULT_VERSION, DOC(dai, DeviceBase, DeviceBase, 11)) + }), py::arg("version") = OpenVINO::DEFAULT_VERSION, DOC(dai, DeviceBase, DeviceBase, 10)) .def(py::init([](OpenVINO::Version version, bool usb2Mode){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev, usb2Mode); - }), py::arg("version"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 13)) + }), py::arg("version"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 11)) .def(py::init([](OpenVINO::Version version, UsbSpeed maxUsbSpeed){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev, maxUsbSpeed); - }), py::arg("version"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 14)) - .def(py::init([](OpenVINO::Version version, const std::string& pathToCmd){ + }), py::arg("version"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 12)) + .def(py::init([](OpenVINO::Version version, const dai::Path& pathToCmd){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(version, dev, pathToCmd); - }), py::arg("version"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 15)) + }), py::arg("version"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 13)) .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, bool usb2Mode){ py::gil_scoped_release release; return std::make_unique(version, deviceInfo, usb2Mode); - }), py::arg("version"), py::arg("deviceDesc"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 18)) + }), py::arg("version"), py::arg("deviceDesc"), py::arg("usb2Mode") = false, DOC(dai, DeviceBase, DeviceBase, 15)) .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, UsbSpeed maxUsbSpeed){ py::gil_scoped_release release; return std::make_unique(version, deviceInfo, maxUsbSpeed); - }), py::arg("version"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 19)) - .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, std::string pathToCmd){ + }), py::arg("version"), py::arg("deviceInfo"), py::arg("maxUsbSpeed"), DOC(dai, DeviceBase, DeviceBase, 16)) + .def(py::init([](OpenVINO::Version version, const DeviceInfo& deviceInfo, dai::Path pathToCmd){ py::gil_scoped_release release; return std::make_unique(version, deviceInfo, pathToCmd); - }), py::arg("version"), py::arg("deviceDesc"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 20)) + }), py::arg("version"), py::arg("deviceDesc"), py::arg("pathToCmd"), DOC(dai, DeviceBase, DeviceBase, 17)) .def(py::init([](typename D::Config config){ auto dev = deviceSearchHelper(); py::gil_scoped_release release; return std::make_unique(config, dev); - }), py::arg("config"), DOC(dai, DeviceBase, DeviceBase, 22)) + }), py::arg("config"), DOC(dai, DeviceBase, DeviceBase, 18)) .def(py::init([](typename D::Config config, const DeviceInfo& deviceInfo){ py::gil_scoped_release release; return std::make_unique(config, deviceInfo); - }), py::arg("config"), py::arg("deviceInfo"), DOC(dai, DeviceBase, DeviceBase, 23)) + }), py::arg("config"), py::arg("deviceInfo"), DOC(dai, DeviceBase, DeviceBase, 19)) ; } diff --git a/src/DeviceBootloaderBindings.cpp b/src/DeviceBootloaderBindings.cpp index 81b2a37d9..b3ab5d59e 100644 --- a/src/DeviceBootloaderBindings.cpp +++ b/src/DeviceBootloaderBindings.cpp @@ -116,25 +116,25 @@ void DeviceBootloaderBindings::bind(pybind11::module& m, void* pCallstack){ .def_static("getFirstAvailableDevice", &DeviceBootloader::getFirstAvailableDevice, DOC(dai, DeviceBootloader, getFirstAvailableDevice)) .def_static("getAllAvailableDevices", &DeviceBootloader::getAllAvailableDevices, DOC(dai, DeviceBootloader, getAllAvailableDevices)) - .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("pathToCmd") = "", py::arg("compress") = false, DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage)) - .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("compress"), DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage, 2)) - .def_static("createDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::createDepthaiApplicationPackage), py::arg("pipeline"), py::arg("pathToCmd") = "", py::arg("compress") = false, DOC(dai, DeviceBootloader, createDepthaiApplicationPackage)) + .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("pathToCmd") = Path{}, py::arg("compress") = false, DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage)) + .def_static("saveDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::saveDepthaiApplicationPackage), py::arg("path"), py::arg("pipeline"), py::arg("compress"), DOC(dai, DeviceBootloader, saveDepthaiApplicationPackage, 2)) + .def_static("createDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::createDepthaiApplicationPackage), py::arg("pipeline"), py::arg("pathToCmd") = Path{}, py::arg("compress") = false, DOC(dai, DeviceBootloader, createDepthaiApplicationPackage)) .def_static("createDepthaiApplicationPackage", py::overload_cast(&DeviceBootloader::createDepthaiApplicationPackage), py::arg("pipeline"), py::arg("compress"), DOC(dai, DeviceBootloader, createDepthaiApplicationPackage, 2)) .def_static("getEmbeddedBootloaderVersion", &DeviceBootloader::getEmbeddedBootloaderVersion, DOC(dai, DeviceBootloader, getEmbeddedBootloaderVersion)) .def_static("getEmbeddedBootloaderBinary", &DeviceBootloader::getEmbeddedBootloaderBinary, DOC(dai, DeviceBootloader, getEmbeddedBootloaderBinary)) .def(py::init(), py::arg("devInfo"), py::arg("allowFlashingBootloader") = false, DOC(dai, DeviceBootloader, DeviceBootloader)) - .def(py::init(), py::arg("devInfo"), py::arg("pathToCmd"), py::arg("allowFlashingBootloader") = false, DOC(dai, DeviceBootloader, DeviceBootloader, 2)) + .def(py::init(), py::arg("devInfo"), py::arg("pathToCmd"), py::arg("allowFlashingBootloader") = false, DOC(dai, DeviceBootloader, DeviceBootloader, 2)) .def("flash", [](DeviceBootloader& db, std::function progressCallback, const Pipeline& pipeline, bool compress) { py::gil_scoped_release release; return db.flash(progressCallback, pipeline, compress); }, py::arg("progressCallback"), py::arg("pipeline"), py::arg("compress") = false, DOC(dai, DeviceBootloader, flash)) .def("flash", [](DeviceBootloader& db, const Pipeline& pipeline, bool compress) { py::gil_scoped_release release; return db.flash(pipeline, compress); }, py::arg("pipeline"), py::arg("compress") = false, DOC(dai, DeviceBootloader, flash, 2)) .def("flashDepthaiApplicationPackage", [](DeviceBootloader& db, std::function progressCallback, std::vector package) { py::gil_scoped_release release; return db.flashDepthaiApplicationPackage(progressCallback, package); }, py::arg("progressCallback"), py::arg("package"), DOC(dai, DeviceBootloader, flashDepthaiApplicationPackage)) .def("flashDepthaiApplicationPackage", [](DeviceBootloader& db, std::vector package) { py::gil_scoped_release release; return db.flashDepthaiApplicationPackage(package); }, py::arg("package"), DOC(dai, DeviceBootloader, flashDepthaiApplicationPackage, 2)) - .def("flashBootloader", [](DeviceBootloader& db, std::function progressCallback, std::string path) { py::gil_scoped_release release; return db.flashBootloader(progressCallback, path); }, py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader)) - .def("flashBootloader", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type, std::function progressCallback, std::string path) { py::gil_scoped_release release; return db.flashBootloader(memory, type, progressCallback, path); }, py::arg("memory"), py::arg("type"), py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader, 2)) + .def("flashBootloader", [](DeviceBootloader& db, std::function progressCallback, const Path& path) { py::gil_scoped_release release; return db.flashBootloader(progressCallback, path); }, py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader)) + .def("flashBootloader", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type, std::function progressCallback, dai::Path path) { py::gil_scoped_release release; return db.flashBootloader(memory, type, progressCallback, path); }, py::arg("memory"), py::arg("type"), py::arg("progressCallback"), py::arg("path") = "", DOC(dai, DeviceBootloader, flashBootloader, 2)) .def("readConfigData", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.readConfigData(memory, type); }, py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, readConfigData)) .def("flashConfigData", [](DeviceBootloader& db, nlohmann::json configData, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigData(configData, memory, type); }, py::arg("configData"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigData)) - .def("flashConfigFile", [](DeviceBootloader& db, std::string configPath, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigFile(configPath, memory, type); }, py::arg("configData"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigFile)) + .def("flashConfigFile", [](DeviceBootloader& db, dai::Path configPath, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigFile(configPath, memory, type); }, py::arg("configData"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigFile)) .def("flashConfigClear", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfigClear(memory, type); }, py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfigClear)) .def("readConfig", [](DeviceBootloader& db, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.readConfig(memory, type); }, py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, readConfig)) .def("flashConfig", [](DeviceBootloader& db, const DeviceBootloader::Config& config, DeviceBootloader::Memory memory, DeviceBootloader::Type type) { py::gil_scoped_release release; return db.flashConfig(config, memory, type); }, py::arg("config"), py::arg("memory") = DeviceBootloader::Memory::AUTO, py::arg("type") = DeviceBootloader::Type::AUTO, DOC(dai, DeviceBootloader, flashConfig)) diff --git a/src/openvino/OpenVINOBindings.cpp b/src/openvino/OpenVINOBindings.cpp index f096f72ef..29cb6da94 100644 --- a/src/openvino/OpenVINOBindings.cpp +++ b/src/openvino/OpenVINOBindings.cpp @@ -57,7 +57,7 @@ void OpenVINOBindings::bind(pybind11::module& m, void* pCallstack){ // Bind OpenVINO::Blob openvinoBlob .def(py::init>(), DOC(dai, OpenVINO, Blob, Blob)) - .def(py::init(), DOC(dai, OpenVINO, Blob, Blob, 2)) + .def(py::init(), DOC(dai, OpenVINO, Blob, Blob, 2)) .def_readwrite("version", &OpenVINO::Blob::version, DOC(dai, OpenVINO, Blob, version)) .def_readwrite("networkInputs", &OpenVINO::Blob::networkInputs, DOC(dai, OpenVINO, Blob, networkInputs)) .def_readwrite("networkOutputs", &OpenVINO::Blob::networkOutputs, DOC(dai, OpenVINO, Blob, networkOutputs)) diff --git a/src/pipeline/AssetManagerBindings.cpp b/src/pipeline/AssetManagerBindings.cpp index 72b3b29f9..ac27e5ed3 100644 --- a/src/pipeline/AssetManagerBindings.cpp +++ b/src/pipeline/AssetManagerBindings.cpp @@ -30,7 +30,7 @@ void AssetManagerBindings::bind(pybind11::module& m, void* pCallstack){ // Bind Asset asset .def(py::init<>()) - .def(py::init()) + .def(py::init()) .def_readonly("key", &Asset::key) // numpy array access - zero copy on access .def_property("data", [](py::object &obj){ @@ -49,7 +49,7 @@ void AssetManagerBindings::bind(pybind11::module& m, void* pCallstack){ .def("addExisting", &AssetManager::addExisting, py::arg("assets"), DOC(dai, AssetManager, addExisting)) .def("set", static_cast (AssetManager::*)(Asset)>(&AssetManager::set), py::arg("asset"), DOC(dai, AssetManager, set)) .def("set", static_cast (AssetManager::*)(const std::string&, Asset)>(&AssetManager::set), py::arg("key"), py::arg("asset"), DOC(dai, AssetManager, set, 2)) - .def("set", static_cast (AssetManager::*)(const std::string& key, const std::string& path, int alignment)>(&AssetManager::set), py::arg("key"), py::arg("path"), py::arg("alignment") = 64, DOC(dai, AssetManager, set, 3)) + .def("set", static_cast (AssetManager::*)(const std::string& key, const dai::Path& path, int alignment)>(&AssetManager::set), py::arg("key"), py::arg("path"), py::arg("alignment") = 64, DOC(dai, AssetManager, set, 3)) .def("set", static_cast (AssetManager::*)(const std::string& key, const std::vector& data, int alignment)>(&AssetManager::set), py::arg("key"), py::arg("data"), py::arg("alignment") = 64, DOC(dai, AssetManager, set, 4)) .def("get", static_cast (AssetManager::*)(const std::string&) const>(&AssetManager::get), py::arg("key"), DOC(dai, AssetManager, get)) .def("get", static_cast (AssetManager::*)(const std::string&)>(&AssetManager::get), py::arg("key"), DOC(dai, AssetManager, get, 2)) diff --git a/src/pipeline/NodeBindings.cpp b/src/pipeline/NodeBindings.cpp index af5a11e39..ea6528561 100644 --- a/src/pipeline/NodeBindings.cpp +++ b/src/pipeline/NodeBindings.cpp @@ -216,7 +216,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ auto edgeDetector = ADD_NODE(EdgeDetector); auto featureTracker = ADD_NODE(FeatureTracker); auto aprilTag = ADD_NODE(AprilTag); - + py::enum_ stereoDepthPresetMode(stereoDepth, "PresetMode", DOC(dai, node, StereoDepth, PresetMode)); @@ -677,7 +677,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ .def_readonly("passthrough", &NeuralNetwork::passthrough, DOC(dai, node, NeuralNetwork, passthrough)) .def("setBlobPath", [](NeuralNetwork& nn, py::object obj){ // Allows to call this function with paths as well as strings - nn.setBlobPath(py::str(obj)); + nn.setBlobPath(dai::Path(py::str(obj))); }, py::arg("path"), DOC(dai, node, NeuralNetwork, setBlobPath)) .def("setNumPoolFrames", &NeuralNetwork::setNumPoolFrames, py::arg("numFrames"), DOC(dai, node, NeuralNetwork, setNumPoolFrames)) .def("setNumInferenceThreads", &NeuralNetwork::setNumInferenceThreads, py::arg("numThreads"), DOC(dai, node, NeuralNetwork, setNumInferenceThreads)) @@ -898,7 +898,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ s.setOutputDepth(enable); HEDLEY_DIAGNOSTIC_POP }) - .def("loadCalibrationFile", [](StereoDepth& s, std::string path){ + .def("loadCalibrationFile", [](StereoDepth& s, dai::Path path){ PyErr_WarnEx(PyExc_DeprecationWarning, "loadCalibrationFile() is deprecated, Use 'Pipeline.setCalibrationData()' instead", 1); HEDLEY_DIAGNOSTIC_PUSH HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED @@ -1224,8 +1224,8 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ .def_readonly("initialConfig", &AprilTag::initialConfig, DOC(dai, node, AprilTag, initialConfig)) .def("setWaitForConfigInput", &AprilTag::setWaitForConfigInput, py::arg("wait"), DOC(dai, node, AprilTag, setWaitForConfigInput)) ; - daiNodeModule.attr("AprilTag").attr("Properties") = aprilTagProperties; - + daiNodeModule.attr("AprilTag").attr("Properties") = aprilTagProperties; + // FeatureTracker node featureTracker .def_readonly("inputConfig", &FeatureTracker::inputConfig, DOC(dai, node, FeatureTracker, inputConfig)) diff --git a/src/pybind11_common.hpp b/src/pybind11_common.hpp index 1669cdf40..258859745 100644 --- a/src/pybind11_common.hpp +++ b/src/pybind11_common.hpp @@ -12,6 +12,7 @@ #include #include #include +#include // Include docstring file #include "docstring.hpp" @@ -24,6 +25,41 @@ namespace pybind11 { namespace detail { struct type_caster> : optional_caster> {}; }} + +namespace pybind11 { namespace detail { + template <> struct type_caster { + public: + + // This macro establishes the name 'dai::Path' in + // function signatures and declares a local variable + // 'value' of type dai::Path + PYBIND11_TYPE_CASTER(dai::Path, _("Path")); + + // Conversion part 1 (Python->C++): convert a PyObject into a dai::Path + // instance or return false upon failure. The second argument + // indicates whether implicit conversions should be applied. + bool load(handle src, bool) { + try { + str pystr = static_cast(src); + value = dai::Path(static_cast(pystr)); + return true; + } catch (...) { + return false; + } + } + + // Conversion part 2 (C++ -> Python): convert an dai::Path instance into + // a Python (string) object. The second and third arguments are used to + // indicate the return value policy and parent object (for + // ``return_value_policy::reference_internal``) and are generally + // ignored by implicit casters. + static handle cast(dai::Path src, return_value_policy /* policy */, handle /* parent */) { + return str{src.u8string()}; + } + }; +}} // namespace pybind11::detail + + namespace py = pybind11; using StackFunction = void (*)(pybind11::module &m, void *pCallstack); From fe5c68694eb2038343399e5944061b93c4e7d21f Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 11:52:46 +0200 Subject: [PATCH 04/13] Added a simple test for UTF-8 path support --- depthai-core | 2 +- tests/CMakeLists.txt | 1 + tests/utf8_support_test.py | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/utf8_support_test.py diff --git a/depthai-core b/depthai-core index ec14f9a98..636cbb569 160000 --- a/depthai-core +++ b/depthai-core @@ -1 +1 @@ -Subproject commit ec14f9a98670f685a2ff21f4c33eb1bc18ce836f +Subproject commit 636cbb56917a867ec3983a85e61209e04f29c9bc diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3aad2e65..3c0eec650 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,7 @@ endif() set(PYBIND11_TEST_FILES "xlink_exceptions_test.cpp" + "utf8_support_test.py" ) string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}") diff --git a/tests/utf8_support_test.py b/tests/utf8_support_test.py new file mode 100644 index 000000000..01f3ca2b3 --- /dev/null +++ b/tests/utf8_support_test.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +import sys + +import pytest + +import depthai as dai + +def test_utf8_path_asset_manager(tmp_path): + + FILE_CONTENTS="Hello World πŸ‘" + + tmp_sneaky_file_dir = tmp_path / "UTF-8 dir πŸ™ˆπŸ™‰πŸ™‰" + tmp_sneaky_file_dir.mkdir() + tmp_sneaky_file_path = tmp_sneaky_file_dir / "sneaky πŸ‘ ΔΔ‡Ε‘Δ‘ΕΎΔ†ΔŒLpΔ‘Ε‘lčk file.txt" + tmp_sneaky_file_path.write_text(FILE_CONTENTS) + + assetManager = dai.AssetManager() + asset = assetManager.set('test', tmp_sneaky_file_path) + assert(bytes(asset.data) == FILE_CONTENTS.encode("utf-8")) From 2459e5f0455f16195b861e0982b74219ed95d17c Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 12:24:56 +0200 Subject: [PATCH 05/13] Added pytest to CI --- .github/workflows/main.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 158f5f455..db9197405 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,6 +61,42 @@ jobs: path: docstrings/ retention-days: 1 + + # Build wheel tests + pytest: + needs: build-docstrings + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Print home directory + run: echo Home directory inside container $HOME + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + + - uses: actions/download-artifact@v2 + with: + name: 'docstrings' + path: docstrings + - name: Specify docstring to use while building the wheel + run: echo "DEPTHAI_PYTHON_DOCSTRINGS_INPUT=$PWD/docstrings/depthai_python_docstring.hpp" >> $GITHUB_ENV + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: 3.10 + + - name: Compile + run: | + cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D DEPTHAI_PYTHON_DOCSTRINGS_INPUT=$PWD/docstrings/depthai_python_docstring.hpp -D DEPTHAI_PYTHON_BUILD_TESTS=ON + cmake --build build --parallel 4 + - name: Test + run: | + cmake --build build --target pytest + + # This job builds wheels for armhf arch (RPi) build-linux-armhf: needs: build-docstrings From 9d44a06acbdeb04e8d0db22f009b524b7cdb5d79 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 12:41:35 +0200 Subject: [PATCH 06/13] Fixed setting python version for pytest --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index db9197405..406e506dd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,7 +86,7 @@ jobs: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: - python-version: 3.10 + python-version: "3.10" - name: Compile run: | @@ -374,7 +374,7 @@ jobs: release: if: startsWith(github.ref, 'refs/tags/v') - needs: [build-linux-armhf, build-windows-x86_64, build-macos-x86_64, build-linux-x86_64, build-linux-arm64] + needs: [pytest, build-linux-armhf, build-windows-x86_64, build-macos-x86_64, build-linux-x86_64, build-linux-arm64] runs-on: ubuntu-latest steps: From 3b8889910f55d3e622ca3264b0f84e7272198503 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 14:56:55 +0200 Subject: [PATCH 07/13] Fixed build and removed some deprecated StereoDepth API --- .github/workflows/main.yml | 12 ++++++++++++ depthai-core | 2 +- src/pipeline/NodeBindings.cpp | 14 -------------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 406e506dd..f32df5ebd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -88,6 +88,18 @@ jobs: with: python-version: "3.10" + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + python -m pip install --upgrade pip + sudo apt install libusb-1.0-0-dev + + - name: Install dependencies (MacOS) + if: matrix.os == 'macos-latest' + run: | + python -m pip install --upgrade pip + brew install libusb + - name: Compile run: | cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D DEPTHAI_PYTHON_DOCSTRINGS_INPUT=$PWD/docstrings/depthai_python_docstring.hpp -D DEPTHAI_PYTHON_BUILD_TESTS=ON diff --git a/depthai-core b/depthai-core index 636cbb569..68edd10ec 160000 --- a/depthai-core +++ b/depthai-core @@ -1 +1 @@ -Subproject commit 636cbb56917a867ec3983a85e61209e04f29c9bc +Subproject commit 68edd10eccdd558a00e7ea0c6e15553c2f4fe93d diff --git a/src/pipeline/NodeBindings.cpp b/src/pipeline/NodeBindings.cpp index ea6528561..e6c02e7a4 100644 --- a/src/pipeline/NodeBindings.cpp +++ b/src/pipeline/NodeBindings.cpp @@ -898,20 +898,6 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ s.setOutputDepth(enable); HEDLEY_DIAGNOSTIC_POP }) - .def("loadCalibrationFile", [](StereoDepth& s, dai::Path path){ - PyErr_WarnEx(PyExc_DeprecationWarning, "loadCalibrationFile() is deprecated, Use 'Pipeline.setCalibrationData()' instead", 1); - HEDLEY_DIAGNOSTIC_PUSH - HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED - s.loadCalibrationFile(path); - HEDLEY_DIAGNOSTIC_POP - }) - .def("loadCalibrationData", [](StereoDepth& s, std::vector data){ - PyErr_WarnEx(PyExc_DeprecationWarning, "loadCalibrationData() is deprecated, Use 'Pipeline.setCalibrationData()' instead", 1); - HEDLEY_DIAGNOSTIC_PUSH - HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED - s.loadCalibrationData(data); - HEDLEY_DIAGNOSTIC_POP - }) .def("setEmptyCalibration", [](StereoDepth& s){ PyErr_WarnEx(PyExc_DeprecationWarning, "setEmptyCalibration() is deprecated, Use 'setRectification(False)' instead", 1); HEDLEY_DIAGNOSTIC_PUSH From bb1eb9ed58396be52fdf50dc02bac89529d11220 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 15:22:03 +0200 Subject: [PATCH 08/13] Fixed Asset binding --- src/pipeline/AssetManagerBindings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pipeline/AssetManagerBindings.cpp b/src/pipeline/AssetManagerBindings.cpp index ac27e5ed3..40a5ddc0c 100644 --- a/src/pipeline/AssetManagerBindings.cpp +++ b/src/pipeline/AssetManagerBindings.cpp @@ -30,7 +30,7 @@ void AssetManagerBindings::bind(pybind11::module& m, void* pCallstack){ // Bind Asset asset .def(py::init<>()) - .def(py::init()) + .def(py::init()) .def_readonly("key", &Asset::key) // numpy array access - zero copy on access .def_property("data", [](py::object &obj){ From 11310c83676250fb04d79595c6e214383e0e1462 Mon Sep 17 00:00:00 2001 From: Martin Peterlin Date: Sat, 9 Apr 2022 17:20:00 +0200 Subject: [PATCH 09/13] Fixed pytest CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f32df5ebd..9616a6eec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -102,7 +102,7 @@ jobs: - name: Compile run: | - cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D DEPTHAI_PYTHON_DOCSTRINGS_INPUT=$PWD/docstrings/depthai_python_docstring.hpp -D DEPTHAI_PYTHON_BUILD_TESTS=ON + cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D DEPTHAI_PYTHON_DOCSTRINGS_INPUT=$PWD/docstrings/depthai_python_docstring.hpp -D DEPTHAI_PYTHON_ENABLE_TESTS=ON cmake --build build --parallel 4 - name: Test run: | From 9911bc68074b70ef21aa8c421c1b792e70ea9c95 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Sat, 9 Apr 2022 19:35:56 +0200 Subject: [PATCH 10/13] Added pytest requirement --- .github/workflows/main.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9616a6eec..844e3b179 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -62,7 +62,7 @@ jobs: retention-days: 1 - # Build wheel tests + # Build and test bindings pytest: needs: build-docstrings strategy: @@ -100,6 +100,10 @@ jobs: python -m pip install --upgrade pip brew install libusb + - name: Install pytest + run: | + python -m pip install pytest + - name: Compile run: | cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D DEPTHAI_PYTHON_DOCSTRINGS_INPUT=$PWD/docstrings/depthai_python_docstring.hpp -D DEPTHAI_PYTHON_ENABLE_TESTS=ON From 66a640f3032c43cac0f95c3a1978102162c0dcb0 Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Mon, 11 Apr 2022 19:16:09 +0200 Subject: [PATCH 11/13] Updated core and CI --- .github/workflows/main.yml | 2 +- depthai-core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 844e3b179..4c6dde903 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -102,7 +102,7 @@ jobs: - name: Install pytest run: | - python -m pip install pytest + python -m pip install pytest numpy - name: Compile run: | diff --git a/depthai-core b/depthai-core index 68edd10ec..45ac63695 160000 --- a/depthai-core +++ b/depthai-core @@ -1 +1 @@ -Subproject commit 68edd10eccdd558a00e7ea0c6e15553c2f4fe93d +Subproject commit 45ac636955e1b23e648d8cdd5961f70a87a14e5c From 0999fa3f17b47e1606f90a7f758791591a9d112d Mon Sep 17 00:00:00 2001 From: TheMarpe Date: Mon, 11 Apr 2022 22:54:26 +0200 Subject: [PATCH 12/13] Modified to use windows-2019 runner for pytest --- .github/workflows/main.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4c6dde903..d56ea0f30 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -67,11 +67,25 @@ jobs: needs: build-docstrings strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-2019, macos-latest] runs-on: ${{ matrix.os }} steps: - name: Print home directory run: echo Home directory inside container $HOME + + - name: Cache .hunter folder + if: matrix.os != 'windows-latest' + uses: actions/cache@v2 + with: + path: ~/.hunter/ + key: hunter-pytest-${{ matrix.os }} + - name: Cache .hunter folder + if: matrix.os == 'windows-latest' + uses: actions/cache@v2 + with: + path: C:/.hunter/ + key: hunter-pytest-${{ matrix.os }} + - uses: actions/checkout@v2 with: submodules: 'recursive' From 9ffc907ce9fc31b92e182cc21f293b00d799b0c1 Mon Sep 17 00:00:00 2001 From: Martin Peterlin Date: Mon, 11 Apr 2022 23:23:22 +0200 Subject: [PATCH 13/13] Fixed CI and utf8 support test --- .github/workflows/main.yml | 2 +- tests/CMakeLists.txt | 5 ++++- tests/utf8_support_test.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d56ea0f30..42997bd37 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -124,7 +124,7 @@ jobs: cmake --build build --parallel 4 - name: Test run: | - cmake --build build --target pytest + cmake --build build --target pytest --config Release # This job builds wheels for armhf arch (RPi) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3c0eec650..15be5f6e0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,7 +19,10 @@ pybind11_add_module(${TARGET_TEST_MODULE} THIN_LTO ${TARGET_TEST_MODULE}.cpp ${P # A single command to compile and run the tests add_custom_target( - pytest COMMAND + pytest + COMMAND + ${CMAKE_COMMAND} -E echo "Setting PYTHONPATH env var to: $${SYS_PATH_SEPARATOR}$${SYS_PATH_SEPARATOR}$ENV{PYTHONPATH}" + COMMAND ${CMAKE_COMMAND} -E env # Python path (to find compiled modules) "PYTHONPATH=$${SYS_PATH_SEPARATOR}$${SYS_PATH_SEPARATOR}$ENV{PYTHONPATH}" diff --git a/tests/utf8_support_test.py b/tests/utf8_support_test.py index 01f3ca2b3..b1d5bbf7f 100644 --- a/tests/utf8_support_test.py +++ b/tests/utf8_support_test.py @@ -12,7 +12,7 @@ def test_utf8_path_asset_manager(tmp_path): tmp_sneaky_file_dir = tmp_path / "UTF-8 dir πŸ™ˆπŸ™‰πŸ™‰" tmp_sneaky_file_dir.mkdir() tmp_sneaky_file_path = tmp_sneaky_file_dir / "sneaky πŸ‘ ΔΔ‡Ε‘Δ‘ΕΎΔ†ΔŒLpΔ‘Ε‘lčk file.txt" - tmp_sneaky_file_path.write_text(FILE_CONTENTS) + tmp_sneaky_file_path.write_bytes(FILE_CONTENTS.encode("utf-8")) assetManager = dai.AssetManager() asset = assetManager.set('test', tmp_sneaky_file_path)