From dd54cb9c17e57e392babd6b5996746d359424e0d Mon Sep 17 00:00:00 2001 From: Anastasia Kuporosova Date: Thu, 31 Mar 2022 21:57:05 +0300 Subject: [PATCH] [Python API] Remove old api class from the new api (#10470) * [Python API] Remove old api class from the new api * start working on refactoring of OVAny * fix tests * fix code-style * remove tuple test * fix test * fix omz hash * one more overload * fix pyfloat * move from_ov_any to utils * code-style * move function from common to utils --- .../python/src/openvino/runtime/__init__.py | 4 +- .../python/src/openvino/runtime/ie_api.py | 46 ------ .../python/src/pyopenvino/core/common.cpp | 132 --------------- .../python/src/pyopenvino/core/common.hpp | 4 - .../src/pyopenvino/core/compiled_model.cpp | 9 +- .../python/src/pyopenvino/core/core.cpp | 12 +- .../src/pyopenvino/core/ie_parameter.cpp | 16 -- .../src/pyopenvino/core/ie_parameter.hpp | 11 -- .../python/src/pyopenvino/graph/any.cpp | 59 +++++-- .../python/src/pyopenvino/graph/any.hpp | 15 -- .../python/src/pyopenvino/graph/rt_map.cpp | 4 +- .../python/src/pyopenvino/pyopenvino.cpp | 2 - .../python/src/pyopenvino/utils/utils.cpp | 155 ++++++++++++++++++ .../python/src/pyopenvino/utils/utils.hpp | 44 ++--- .../test_inference_engine/test_input_node.py | 6 +- .../test_output_const_node.py | 4 +- .../python/tests/test_ngraph/test_any.py | 5 - .../python/tests/test_ngraph/test_basic.py | 4 +- 18 files changed, 243 insertions(+), 289 deletions(-) delete mode 100644 src/bindings/python/src/pyopenvino/core/ie_parameter.cpp delete mode 100644 src/bindings/python/src/pyopenvino/core/ie_parameter.hpp create mode 100644 src/bindings/python/src/pyopenvino/utils/utils.cpp diff --git a/src/bindings/python/src/openvino/runtime/__init__.py b/src/bindings/python/src/openvino/runtime/__init__.py index f40efa258d2..2726fe8a56f 100644 --- a/src/bindings/python/src/openvino/runtime/__init__.py +++ b/src/bindings/python/src/openvino/runtime/__init__.py @@ -32,15 +32,13 @@ from openvino.pyopenvino import Coordinate from openvino.pyopenvino import Layout from openvino.pyopenvino import ConstOutput from openvino.pyopenvino import layout_helpers +from openvino.pyopenvino import OVAny from openvino.pyopenvino import RTMap - from openvino.runtime.ie_api import Core from openvino.runtime.ie_api import CompiledModel from openvino.runtime.ie_api import InferRequest from openvino.runtime.ie_api import AsyncInferQueue -from openvino.runtime.ie_api import OVAny from openvino.pyopenvino import Version -from openvino.pyopenvino import Parameter from openvino.pyopenvino import Tensor from openvino.pyopenvino import Extension from openvino.pyopenvino import ProfilingInfo diff --git a/src/bindings/python/src/openvino/runtime/ie_api.py b/src/bindings/python/src/openvino/runtime/ie_api.py index a49f6f62ee5..3d8262bc615 100644 --- a/src/bindings/python/src/openvino/runtime/ie_api.py +++ b/src/bindings/python/src/openvino/runtime/ie_api.py @@ -11,7 +11,6 @@ from openvino.pyopenvino import InferRequest as InferRequestBase from openvino.pyopenvino import AsyncInferQueue as AsyncInferQueueBase from openvino.pyopenvino import ConstOutput from openvino.pyopenvino import Tensor -from openvino.pyopenvino import OVAny as OVAnyBase from openvino.runtime.utils.types import get_dtype @@ -345,48 +344,3 @@ def compile_model(model_path: str) -> CompiledModel: """ core = Core() return core.compile_model(model_path, "AUTO") - - -class OVAny(OVAnyBase): - """OVAny wrapper. - - Wrapper provides some useful overloads for simple built-in Python types. - - Access to the `OVAny` value is direct if it is a built-in Python data type. - - :Example: - .. code-block:: ipython - - any = OVAny([1, 2]) - print(any[0]) - - Output: 2 - - Otherwise if `OVAny` value is a custom data type (for example user class), - access to the value is possible by `get()` method or property 'value'. - - :Example: - .. code-block:: python - - class Test: - def __init__(self): - self.data = "test" - - any = OVAny(Test()) - print(any.value.data) - """ - - def __getitem__(self, key: Union[str, int]) -> Any: - return self.value[key] - - def __get__(self) -> Any: - return self.value - - def __setitem__(self, key: Union[str, int], val: Any) -> None: - self.value[key] = val - - def __set__(self, val: Any) -> None: - self.value = val - - def __len__(self) -> int: - return len(self.value) diff --git a/src/bindings/python/src/pyopenvino/core/common.cpp b/src/bindings/python/src/pyopenvino/core/common.cpp index 997dcb22927..3540d9fef44 100644 --- a/src/bindings/python/src/pyopenvino/core/common.cpp +++ b/src/bindings/python/src/pyopenvino/core/common.cpp @@ -293,138 +293,6 @@ void set_request_tensors(ov::InferRequest& request, const py::dict& inputs) { } } -PyAny from_ov_any(const ov::Any& any) { - // Check for py::object - if (any.is()) { - return any.as(); - } - // Check for std::string - else if (any.is()) { - return PyUnicode_FromString(any.as().c_str()); - } - // Check for int - else if (any.is()) { - auto val = any.as(); - return PyLong_FromLong((long)val); - } else if (any.is()) { - auto val = any.as(); - return PyLong_FromLong((long)val); - } - // Check for unsinged int - else if (any.is()) { - auto val = any.as(); - return PyLong_FromLong((unsigned long)val); - } - // Check for float - else if (any.is()) { - auto val = any.as(); - return PyFloat_FromDouble((double)val); - } else if (any.is()) { - auto val = any.as(); - return PyFloat_FromDouble(val); - } - // Check for bool - else if (any.is()) { - auto val = any.as(); - return val ? Py_True : Py_False; - } - // Check for std::vector - else if (any.is>()) { - auto val = any.as>(); - PyObject* list = PyList_New(0); - for (const auto& it : val) { - PyObject* str_val = PyUnicode_FromString(it.c_str()); - PyList_Append(list, str_val); - } - return list; - } - // Check for std::vector - else if (any.is>()) { - auto val = any.as>(); - PyObject* list = PyList_New(0); - for (const auto& it : val) { - PyList_Append(list, PyLong_FromLong(it)); - } - return list; - } - // Check for std::vector - else if (any.is>()) { - auto val = any.as>(); - PyObject* list = PyList_New(0); - for (const auto& it : val) { - PyList_Append(list, PyLong_FromLong(it)); - } - return list; - } - // Check for std::vector - else if (any.is>()) { - auto val = any.as>(); - PyObject* list = PyList_New(0); - for (const auto& it : val) { - PyList_Append(list, PyLong_FromLong(it)); - } - return list; - } - // Check for std::vector - else if (any.is>()) { - auto val = any.as>(); - PyObject* list = PyList_New(0); - for (const auto& it : val) { - PyList_Append(list, PyFloat_FromDouble((double)it)); - } - return list; - } - // Check for std::tuple - else if (any.is>()) { - auto val = any.as>(); - PyObject* tuple = PyTuple_New(2); - PyTuple_SetItem(tuple, 0, PyLong_FromUnsignedLong((unsigned long)std::get<0>(val))); - PyTuple_SetItem(tuple, 1, PyLong_FromUnsignedLong((unsigned long)std::get<1>(val))); - return tuple; - } - // Check for std::tuple - else if (any.is>()) { - auto val = any.as>(); - PyObject* tuple = PyTuple_New(3); - PyTuple_SetItem(tuple, 0, PyLong_FromUnsignedLong((unsigned long)std::get<0>(val))); - PyTuple_SetItem(tuple, 1, PyLong_FromUnsignedLong((unsigned long)std::get<1>(val))); - PyTuple_SetItem(tuple, 2, PyLong_FromUnsignedLong((unsigned long)std::get<2>(val))); - return tuple; - } - // Check for std::map - else if (any.is>()) { - auto val = any.as>(); - PyObject* dict = PyDict_New(); - for (const auto& it : val) { - PyDict_SetItemString(dict, it.first.c_str(), PyUnicode_FromString(it.second.c_str())); - } - return dict; - } - // Check for std::map - else if (any.is>()) { - auto val = any.as>(); - PyObject* dict = PyDict_New(); - for (const auto& it : val) { - PyDict_SetItemString(dict, it.first.c_str(), PyLong_FromLong((long)it.second)); - } - return dict; - } - // Check for std::vector - else if (any.is>()) { - auto val = any.as>(); - PyObject* dict = PyDict_New(); - for (const auto& it : val) { - std::string property_name = it; - std::string mutability = it.is_mutable() ? "RW" : "RO"; - PyDict_SetItemString(dict, property_name.c_str(), PyUnicode_FromString(mutability.c_str())); - } - return dict; - } else { - PyErr_SetString(PyExc_TypeError, "Failed to convert parameter to Python representation!"); - return (PyObject*)NULL; - } -} - uint32_t get_optimal_number_of_requests(const ov::CompiledModel& actual) { try { auto supported_properties = actual.get_property(ov::supported_properties); diff --git a/src/bindings/python/src/pyopenvino/core/common.hpp b/src/bindings/python/src/pyopenvino/core/common.hpp index f3f9ad0be03..36c0326fd12 100644 --- a/src/bindings/python/src/pyopenvino/core/common.hpp +++ b/src/bindings/python/src/pyopenvino/core/common.hpp @@ -14,11 +14,9 @@ #include #include "Python.h" -#include "ie_common.h" #include "openvino/runtime/compiled_model.hpp" #include "openvino/runtime/infer_request.hpp" #include "openvino/runtime/tensor.hpp" -#include "openvino/runtime/properties.hpp" #include "openvino/pass/serialize.hpp" #include "pyopenvino/core/containers.hpp" #include "pyopenvino/graph/any.hpp" @@ -50,8 +48,6 @@ const Containers::TensorIndexMap cast_to_tensor_index_map(const py::dict& inputs void set_request_tensors(ov::InferRequest& request, const py::dict& inputs); -PyAny from_ov_any(const ov::Any& any); - uint32_t get_optimal_number_of_requests(const ov::CompiledModel& actual); py::dict outputs_to_dict(const std::vector>& outputs, ov::InferRequest& request); diff --git a/src/bindings/python/src/pyopenvino/core/compiled_model.cpp b/src/bindings/python/src/pyopenvino/core/compiled_model.cpp index c56a545f2d3..158d7e2447a 100644 --- a/src/bindings/python/src/pyopenvino/core/compiled_model.cpp +++ b/src/bindings/python/src/pyopenvino/core/compiled_model.cpp @@ -7,11 +7,10 @@ #include #include -#include - #include "common.hpp" #include "pyopenvino/core/containers.hpp" #include "pyopenvino/core/infer_request.hpp" +#include "pyopenvino/utils/utils.hpp" PYBIND11_MAKE_OPAQUE(Containers::TensorIndexMap); PYBIND11_MAKE_OPAQUE(Containers::TensorNameMap); @@ -148,9 +147,9 @@ void regclass_CompiledModel(py::module m) { cls.def( "set_property", [](ov::CompiledModel& self, const std::map& properties) { - std::map properties_to_cpp; + std::map properties_to_cpp; for (const auto& property : properties) { - properties_to_cpp[property.first] = PyAny(property.second); + properties_to_cpp[property.first] = ov::Any(py_object_to_any(property.second)); } self.set_property({properties_to_cpp.begin(), properties_to_cpp.end()}); }, @@ -166,7 +165,7 @@ void regclass_CompiledModel(py::module m) { cls.def( "get_property", [](ov::CompiledModel& self, const std::string& name) -> py::object { - return Common::from_ov_any(self.get_property(name)).as(); + return Common::utils::from_ov_any(self.get_property(name)); }, py::arg("name"), R"( diff --git a/src/bindings/python/src/pyopenvino/core/core.cpp b/src/bindings/python/src/pyopenvino/core/core.cpp index 866315052a3..36fc0951acf 100644 --- a/src/bindings/python/src/pyopenvino/core/core.cpp +++ b/src/bindings/python/src/pyopenvino/core/core.cpp @@ -10,9 +10,9 @@ #include #include #include -#include #include "common.hpp" +#include "pyopenvino/utils/utils.hpp" namespace py = pybind11; @@ -35,9 +35,9 @@ void regclass_Core(py::module m) { cls.def( "set_property", [](ov::Core& self, const std::map& properties) { - std::map properties_to_cpp; + std::map properties_to_cpp; for (const auto& property : properties) { - properties_to_cpp[property.first] = PyAny(property.second); + properties_to_cpp[property.first] = ov::Any(py_object_to_any(property.second)); } self.set_property({properties_to_cpp.begin(), properties_to_cpp.end()}); }, @@ -52,9 +52,9 @@ void regclass_Core(py::module m) { cls.def( "set_property", [](ov::Core& self, const std::string& device_name, const std::map& properties) { - std::map properties_to_cpp; + std::map properties_to_cpp; for (const auto& property : properties) { - properties_to_cpp[property.first] = PyAny(property.second); + properties_to_cpp[property.first] = ov::Any(py_object_to_any(property.second)); } self.set_property(device_name, {properties_to_cpp.begin(), properties_to_cpp.end()}); }, @@ -388,7 +388,7 @@ void regclass_Core(py::module m) { cls.def( "get_property", [](ov::Core& self, const std::string& device_name, const std::string& name) -> py::object { - return Common::from_ov_any(self.get_property(device_name, name)).as(); + return Common::utils::from_ov_any(self.get_property(device_name, name)); }, py::arg("device_name"), py::arg("name"), diff --git a/src/bindings/python/src/pyopenvino/core/ie_parameter.cpp b/src/bindings/python/src/pyopenvino/core/ie_parameter.cpp deleted file mode 100644 index 93c2cc412d6..00000000000 --- a/src/bindings/python/src/pyopenvino/core/ie_parameter.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2018-2022 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_parameter.hpp" - -#include - -namespace py = pybind11; - -void regclass_Parameter(py::module m) { - py::class_> cls(m, "Parameter"); - - cls.def(py::init()); - cls.def(py::init()); -} diff --git a/src/bindings/python/src/pyopenvino/core/ie_parameter.hpp b/src/bindings/python/src/pyopenvino/core/ie_parameter.hpp deleted file mode 100644 index f70478a21ce..00000000000 --- a/src/bindings/python/src/pyopenvino/core/ie_parameter.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (C) 2018-2022 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include - -namespace py = pybind11; - -void regclass_Parameter(py::module m); diff --git a/src/bindings/python/src/pyopenvino/graph/any.cpp b/src/bindings/python/src/pyopenvino/graph/any.cpp index 715f49b2d42..a6a25cda93b 100644 --- a/src/bindings/python/src/pyopenvino/graph/any.cpp +++ b/src/bindings/python/src/pyopenvino/graph/any.cpp @@ -6,37 +6,64 @@ #include -#include "pyopenvino/core/common.hpp" #include "pyopenvino/graph/any.hpp" +#include "pyopenvino/utils/utils.hpp" namespace py = pybind11; void regclass_graph_Any(py::module m) { - py::class_> ov_any(m, "OVAny", py::module_local()); + py::class_> ov_any(m, "OVAny"); + ov_any.doc() = "openvino.runtime.OVAny provides object wrapper for OpenVINO" "ov::Any class. It allows to pass different types of objects" "into C++ based core of the project."; - ov_any.def(py::init()); + ov_any.def(py::init([](py::object& input_value) { + return ov::Any(py_object_to_any(input_value)); + })); - ov_any.def("__repr__", [](const PyAny& self) { + ov_any.def("__repr__", [](const ov::Any& self) { std::stringstream ret; self.print(ret); return ret.str(); }); - ov_any.def("__eq__", [](const PyAny& a, const PyAny& b) -> bool { + + ov_any.def("__getitem__", [](const ov::Any& self, py::object& k) { + return Common::utils::from_ov_any(self)[k]; + }); + + ov_any.def("__setitem__", [](const ov::Any& self, py::object& k, const std::string& v) { + Common::utils::from_ov_any(self)[k] = v; + }); + + ov_any.def("__setitem__", [](const ov::Any& self, py::object& k, const int64_t& v) { + Common::utils::from_ov_any(self)[k] = v; + }); + + ov_any.def("__get__", [](const ov::Any& self) { + return Common::utils::from_ov_any(self); + }); + + ov_any.def("__set__", [](const ov::Any& self, const ov::Any& val) { + Common::utils::from_ov_any(self) = Common::utils::from_ov_any(val); + }); + + ov_any.def("__len__", [](const ov::Any& self) { + py::handle some_object = Common::utils::from_ov_any(self); + PyObject* source = some_object.ptr(); + return PyObject_Length(source); + }); + + ov_any.def("__eq__", [](const ov::Any& a, const ov::Any& b) -> bool { return a == b; }); - ov_any.def("__eq__", [](const PyAny& a, const ov::Any& b) -> bool { - return a == b; - }); - ov_any.def("__eq__", [](const PyAny& a, py::object b) -> bool { - return a == PyAny(b); + ov_any.def("__eq__", [](const ov::Any& a, py::object& b) -> bool { + return a == ov::Any(py_object_to_any(b)); }); ov_any.def( "get", - [](const PyAny& self) -> py::object { - return self.as(); + [](const ov::Any& self) -> py::object { + return Common::utils::from_ov_any(self); }, R"( :return: Value of this OVAny. @@ -44,8 +71,8 @@ void regclass_graph_Any(py::module m) { )"); ov_any.def( "set", - [](PyAny& self, py::object value) { - self = PyAny(value); + [](ov::Any& self, py::object& value) { + self = ov::Any(py_object_to_any(value)); }, R"( :param: Value to be set in OVAny. @@ -53,8 +80,8 @@ void regclass_graph_Any(py::module m) { )"); ov_any.def_property_readonly( "value", - [](const PyAny& self) { - return self.as(); + [](const ov::Any& self) { + return Common::utils::from_ov_any(self); }, R"( :return: Value of this OVAny. diff --git a/src/bindings/python/src/pyopenvino/graph/any.hpp b/src/bindings/python/src/pyopenvino/graph/any.hpp index 70cf6214b1e..2b74880d869 100644 --- a/src/bindings/python/src/pyopenvino/graph/any.hpp +++ b/src/bindings/python/src/pyopenvino/graph/any.hpp @@ -6,21 +6,6 @@ #include -#include -#include - -#include "Python.h" -#include "openvino/core/any.hpp" // ov::RuntimeAttribute - namespace py = pybind11; void regclass_graph_Any(py::module m); - -class PyAny : public ov::Any { -public: - using ov::Any::Any; - PyAny() = default; - PyAny(py::object object) : ov::Any(object) {} - PyAny(PyObject* object) : ov::Any(py::reinterpret_borrow(object)) {} - PyAny(const ov::Any& any) : ov::Any(any) {} -}; diff --git a/src/bindings/python/src/pyopenvino/graph/rt_map.cpp b/src/bindings/python/src/pyopenvino/graph/rt_map.cpp index 95fae8f0ed2..f950f223e19 100644 --- a/src/bindings/python/src/pyopenvino/graph/rt_map.cpp +++ b/src/bindings/python/src/pyopenvino/graph/rt_map.cpp @@ -4,6 +4,7 @@ #include "pyopenvino/graph/rt_map.hpp" +#include #include #include #include @@ -18,6 +19,7 @@ #include "pyopenvino/core/common.hpp" #include "pyopenvino/graph/any.hpp" #include "pyopenvino/graph/node.hpp" +#include "pyopenvino/utils/utils.hpp" namespace py = pybind11; @@ -37,7 +39,7 @@ void regclass_graph_PyRTMap(py::module m) { m[k] = v; }); py_map.def("__getitem__", [](PyRTMap& m, const std::string& k) -> py::object { - return Common::from_ov_any(m[k]).as(); + return Common::utils::from_ov_any(m[k]); }); py_map.def( "__bool__", diff --git a/src/bindings/python/src/pyopenvino/pyopenvino.cpp b/src/bindings/python/src/pyopenvino/pyopenvino.cpp index c38cab64ffe..8894da14f09 100644 --- a/src/bindings/python/src/pyopenvino/pyopenvino.cpp +++ b/src/bindings/python/src/pyopenvino/pyopenvino.cpp @@ -26,7 +26,6 @@ #include "pyopenvino/core/containers.hpp" #include "pyopenvino/core/core.hpp" #include "pyopenvino/core/extension.hpp" -#include "pyopenvino/core/ie_parameter.hpp" #include "pyopenvino/core/infer_request.hpp" #include "pyopenvino/core/offline_transformations.hpp" #include "pyopenvino/core/profiling_info.hpp" @@ -199,7 +198,6 @@ PYBIND11_MODULE(pyopenvino, m) { regclass_InferRequest(m); regclass_VariableState(m); regclass_Version(m); - regclass_Parameter(m); regclass_AsyncInferQueue(m); regclass_ProfilingInfo(m); regclass_Extension(m); diff --git a/src/bindings/python/src/pyopenvino/utils/utils.cpp b/src/bindings/python/src/pyopenvino/utils/utils.cpp new file mode 100644 index 00000000000..f39fdf5ae14 --- /dev/null +++ b/src/bindings/python/src/pyopenvino/utils/utils.cpp @@ -0,0 +1,155 @@ +// Copyright (C) 2018-2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "pyopenvino/utils/utils.hpp" + +#include + +#include +#include +#include +#include + +#include "Python.h" +#include "openvino/runtime/properties.hpp" + +namespace Common { +namespace utils { + +py::object from_ov_any(const ov::Any& any) { + // Check for py::object + if (any.is()) { + return any.as(); + } + // Check for std::string + else if (any.is()) { + return py::cast(PyUnicode_FromString(any.as().c_str())); + } + // Check for int + else if (any.is()) { + return py::cast(PyLong_FromLong(any.as())); + } else if (any.is()) { + return py::cast(PyLong_FromLong(any.as())); + } + // Check for unsigned int + else if (any.is()) { + return py::cast(PyLong_FromLong(any.as())); + } + // Check for float + else if (any.is()) { + return py::cast(PyFloat_FromDouble(any.as())); + } else if (any.is()) { + return py::cast(PyFloat_FromDouble(any.as())); + } + // Check for bool + else if (any.is()) { + return py::cast(any.as() ? Py_True : Py_False); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* list = PyList_New(0); + for (const auto& it : val) { + PyObject* str_val = PyUnicode_FromString(it.c_str()); + PyList_Append(list, str_val); + } + return py::cast(list); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* list = PyList_New(0); + for (const auto& it : val) { + PyList_Append(list, PyLong_FromLong(it)); + } + return py::cast(list); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* list = PyList_New(0); + for (const auto& it : val) { + PyList_Append(list, PyLong_FromLong(it)); + } + return py::cast(list); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* list = PyList_New(0); + for (const auto& it : val) { + PyList_Append(list, PyLong_FromLong(it)); + } + return py::cast(list); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* list = PyList_New(0); + for (const auto& it : val) { + PyList_Append(list, PyFloat_FromDouble((double)it)); + } + return py::cast(list); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* list = PyList_New(0); + for (const auto& it : val) { + PyList_Append(list, PyFloat_FromDouble(it)); + } + return py::cast(list); + } + // Check for std::tuple + else if (any.is>()) { + auto val = any.as>(); + PyObject* tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, PyLong_FromUnsignedLong((unsigned long)std::get<0>(val))); + PyTuple_SetItem(tuple, 1, PyLong_FromUnsignedLong((unsigned long)std::get<1>(val))); + return py::cast(tuple); + } + // Check for std::tuple + else if (any.is>()) { + auto val = any.as>(); + PyObject* tuple = PyTuple_New(3); + PyTuple_SetItem(tuple, 0, PyLong_FromUnsignedLong((unsigned long)std::get<0>(val))); + PyTuple_SetItem(tuple, 1, PyLong_FromUnsignedLong((unsigned long)std::get<1>(val))); + PyTuple_SetItem(tuple, 2, PyLong_FromUnsignedLong((unsigned long)std::get<2>(val))); + return py::cast(tuple); + } + // Check for std::map + else if (any.is>()) { + auto val = any.as>(); + PyObject* dict = PyDict_New(); + for (const auto& it : val) { + PyDict_SetItemString(dict, it.first.c_str(), PyUnicode_FromString(it.second.c_str())); + } + return py::cast(dict); + } + // Check for std::map + else if (any.is>()) { + auto val = any.as>(); + PyObject* dict = PyDict_New(); + for (const auto& it : val) { + PyDict_SetItemString(dict, it.first.c_str(), PyLong_FromLong((long)it.second)); + } + return py::cast(dict); + } + // Check for std::vector + else if (any.is>()) { + auto val = any.as>(); + PyObject* dict = PyDict_New(); + for (const auto& it : val) { + std::string property_name = it; + std::string mutability = it.is_mutable() ? "RW" : "RO"; + PyDict_SetItemString(dict, property_name.c_str(), PyUnicode_FromString(mutability.c_str())); + } + return py::cast(dict); + } else { + PyErr_SetString(PyExc_TypeError, "Failed to convert parameter to Python representation!"); + return py::cast((PyObject*)NULL); + } +} +}; // namespace utils +}; // namespace Common \ No newline at end of file diff --git a/src/bindings/python/src/pyopenvino/utils/utils.hpp b/src/bindings/python/src/pyopenvino/utils/utils.hpp index 4d862594f00..5fffcd058a3 100644 --- a/src/bindings/python/src/pyopenvino/utils/utils.hpp +++ b/src/bindings/python/src/pyopenvino/utils/utils.hpp @@ -7,26 +7,29 @@ #include #include -ov::Any py_object_to_any(const pybind11::object& py_obj) { - if (pybind11::isinstance(py_obj)) { +namespace py = pybind11; + +namespace Common { +namespace utils { + + py::object from_ov_any(const ov::Any &any); +}; // namespace utils +}; // namespace Common + +inline ov::Any py_object_to_any(const py::object& py_obj) { + if (py::isinstance(py_obj)) { return py_obj.cast(); - } else if (pybind11::isinstance(py_obj)) { + } else if (py::isinstance(py_obj)) { return py_obj.cast(); - } else if (pybind11::isinstance(py_obj)) { + } else if (py::isinstance(py_obj)) { return py_obj.cast(); - } else if (pybind11::isinstance(py_obj)) { + } else if (py::isinstance(py_obj)) { return py_obj.cast(); - } else if (pybind11::isinstance(py_obj)) { - auto _list = py_obj.cast(); - enum class PY_TYPE : int { - UNKNOWN = 0, - STR, - INT, - FLOAT, - BOOL - }; + } else if (py::isinstance(py_obj)) { + auto _list = py_obj.cast(); + enum class PY_TYPE : int { UNKNOWN = 0, STR, INT, FLOAT, BOOL }; PY_TYPE detected_type = PY_TYPE::UNKNOWN; - for (const auto &it: _list) { + for (const auto& it : _list) { auto check_type = [&](PY_TYPE type) { if (detected_type == PY_TYPE::UNKNOWN || detected_type == type) { detected_type = type; @@ -34,13 +37,13 @@ ov::Any py_object_to_any(const pybind11::object& py_obj) { } OPENVINO_ASSERT("Incorrect attribute. Mixed types in the list are not allowed."); }; - if (pybind11::isinstance(it)) { + if (py::isinstance(it)) { check_type(PY_TYPE::STR); - } else if (pybind11::isinstance(it)) { + } else if (py::isinstance(it)) { check_type(PY_TYPE::INT); - } else if (pybind11::isinstance(it)) { + } else if (py::isinstance(it)) { check_type(PY_TYPE::FLOAT); - } else if (pybind11::isinstance(it)) { + } else if (py::isinstance(it)) { check_type(PY_TYPE::BOOL); } } @@ -57,6 +60,9 @@ ov::Any py_object_to_any(const pybind11::object& py_obj) { default: OPENVINO_ASSERT(false, "Unsupported attribute type."); } + + } else if (py::isinstance(py_obj)) { + return py_obj; } OPENVINO_ASSERT(false, "Unsupported attribute type."); } diff --git a/src/bindings/python/tests/test_inference_engine/test_input_node.py b/src/bindings/python/tests/test_inference_engine/test_input_node.py index 87b87f36983..c3e66feefee 100644 --- a/src/bindings/python/tests/test_inference_engine/test_input_node.py +++ b/src/bindings/python/tests/test_inference_engine/test_input_node.py @@ -4,12 +4,12 @@ import os from ..conftest import model_path -from openvino.runtime import Input, Shape, PartialShape, Type, Parameter, \ +from openvino.runtime import Input, Shape, PartialShape, Type, \ RTMap from openvino.pyopenvino import DescriptorTensor import openvino.runtime.opset8 as ops -from openvino.runtime import Core +from openvino.runtime import Core, OVAny is_myriad = os.environ.get("TEST_DEVICE") == "MYRIAD" test_net_xml, test_net_bin = model_path(is_myriad) @@ -146,4 +146,4 @@ def test_input_update_rt_info(device): rt["test12345"] = "test" for k, v in input_node.get_rt_info().items(): assert k == "test12345" - assert isinstance(v, Parameter) + assert isinstance(v, OVAny) diff --git a/src/bindings/python/tests/test_inference_engine/test_output_const_node.py b/src/bindings/python/tests/test_inference_engine/test_output_const_node.py index 00d4c2522f8..cbe4655ba79 100644 --- a/src/bindings/python/tests/test_inference_engine/test_output_const_node.py +++ b/src/bindings/python/tests/test_inference_engine/test_output_const_node.py @@ -6,7 +6,7 @@ import os from ..conftest import model_path import openvino.runtime.opset8 as ops from openvino.runtime import ConstOutput, Shape, PartialShape, Type, \ - Output, Parameter, RTMap + Output, RTMap, OVAny from openvino.runtime import Core @@ -130,7 +130,7 @@ def test_update_rt_info(device): rt["test12345"] = "test" for k, v in output_node.get_rt_info().items(): assert k == "test12345" - assert isinstance(v, Parameter) + assert isinstance(v, OVAny) def test_operations(): diff --git a/src/bindings/python/tests/test_ngraph/test_any.py b/src/bindings/python/tests/test_ngraph/test_any.py index 28860107e9c..3b9c2c24e03 100644 --- a/src/bindings/python/tests/test_ngraph/test_any.py +++ b/src/bindings/python/tests/test_ngraph/test_any.py @@ -42,11 +42,6 @@ def test_any_float_list(): assert isinstance(v[0], float) -def test_any_tuple(): - v = OVAny((2, 1)) - assert isinstance(v.value, tuple) - - def test_any_bool(): v = OVAny(False) assert isinstance(v.value, bool) diff --git a/src/bindings/python/tests/test_ngraph/test_basic.py b/src/bindings/python/tests/test_ngraph/test_basic.py index da0f39531ba..1b63dbe9a71 100644 --- a/src/bindings/python/tests/test_ngraph/test_basic.py +++ b/src/bindings/python/tests/test_ngraph/test_basic.py @@ -9,12 +9,10 @@ import pytest import openvino.runtime.opset8 as ops import openvino.runtime as ov -from openvino.pyopenvino import OVAny - from openvino.runtime.exceptions import UserInputError from openvino.runtime import Model, PartialShape, Shape, Type, layout_helpers from openvino.runtime import Strides, AxisVector, Coordinate, CoordinateDiff -from openvino.runtime import Tensor +from openvino.runtime import Tensor, OVAny from openvino.pyopenvino import DescriptorTensor from openvino.runtime.op import Parameter from tests.runtime import get_runtime