aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/udfs/common/python/bindings/py_variant.cpp
diff options
context:
space:
mode:
authorimunkin <imunkin@yandex-team.com>2024-11-08 10:00:23 +0300
committerimunkin <imunkin@yandex-team.com>2024-11-08 10:12:13 +0300
commita784a2f943d6e15caa6241e2e96d80aac6dbf375 (patch)
tree05f1e5366c916b988a8afb75bdab8ddeee0f6e6d /yql/essentials/udfs/common/python/bindings/py_variant.cpp
parentd70137a7b530ccaa52834274913bbb5a3d1ca06e (diff)
downloadydb-a784a2f943d6e15caa6241e2e96d80aac6dbf375.tar.gz
Move yql/udfs/common/ to /yql/essentials YQL-19206
Except the following directories: * clickhouse/client * datetime * knn * roaring commit_hash:c7da95636144d28db109d6b17ddc762e9bacb59f
Diffstat (limited to 'yql/essentials/udfs/common/python/bindings/py_variant.cpp')
-rw-r--r--yql/essentials/udfs/common/python/bindings/py_variant.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/yql/essentials/udfs/common/python/bindings/py_variant.cpp b/yql/essentials/udfs/common/python/bindings/py_variant.cpp
new file mode 100644
index 0000000000..ab222b3432
--- /dev/null
+++ b/yql/essentials/udfs/common/python/bindings/py_variant.cpp
@@ -0,0 +1,97 @@
+#include "py_variant.h"
+#include "py_cast.h"
+#include "py_errors.h"
+#include "py_utils.h"
+
+#include <yql/essentials/public/udf/udf_value.h>
+#include <yql/essentials/public/udf/udf_value_builder.h>
+#include <yql/essentials/public/udf/udf_type_inspection.h>
+
+
+using namespace NKikimr;
+
+namespace NPython {
+
+//////////////////////////////////////////////////////////////////////////////
+// public functions
+//////////////////////////////////////////////////////////////////////////////
+TPyObjectPtr ToPyVariant(
+ const TPyCastContext::TPtr& castCtx,
+ const NUdf::TType* type,
+ const NUdf::TUnboxedValuePod& value)
+{
+ auto& th = *castCtx->PyCtx->TypeInfoHelper;
+ NUdf::TVariantTypeInspector varInsp(th, type);
+ const NUdf::TType* subType = varInsp.GetUnderlyingType();
+ ui32 index = value.GetVariantIndex();
+ auto item = value.GetVariantItem();
+
+ const NUdf::TType* itemType = nullptr;
+ if (auto tupleInsp = NUdf::TTupleTypeInspector(th, subType)) {
+ itemType = tupleInsp.GetElementType(index);
+ TPyObjectPtr pyIndex = PyCast<ui32>(index);
+ TPyObjectPtr pyItem = ToPyObject(castCtx, itemType, item);
+ return PyTuple_Pack(2, pyIndex.Get(), pyItem.Get());
+ } else if (auto structInsp = NUdf::TStructTypeInspector(th, subType)) {
+ itemType = structInsp.GetMemberType(index);
+ TPyObjectPtr pyName = ToPyUnicode<NUdf::TStringRef>(
+ structInsp.GetMemberName(index));
+ TPyObjectPtr pyItem = ToPyObject(castCtx, itemType, item);
+ return PyTuple_Pack(2, pyName.Get(), pyItem.Get());
+ }
+
+ throw yexception() << "Cannot get Variant item type";
+}
+
+NUdf::TUnboxedValue FromPyVariant(
+ const TPyCastContext::TPtr& castCtx,
+ const NUdf::TType* type,
+ PyObject* value)
+{
+ PY_ENSURE(PyTuple_Check(value),
+ "Expected to get Tuple, but got " << Py_TYPE(value)->tp_name);
+
+ Py_ssize_t tupleSize = PyTuple_GET_SIZE(value);
+ PY_ENSURE(tupleSize == 2,
+ "Expected to get Tuple with 2 elements, but got "
+ << tupleSize << " elements");
+
+ auto& th = *castCtx->PyCtx->TypeInfoHelper;
+ NUdf::TVariantTypeInspector varInsp(th, type);
+ const NUdf::TType* subType = varInsp.GetUnderlyingType();
+
+ PyObject* el0 = PyTuple_GET_ITEM(value, 0);
+ PyObject* el1 = PyTuple_GET_ITEM(value, 1);
+
+ ui32 index;
+ NUdf::TStringRef name;
+ if (TryPyCast(el0, index)) {
+ if (auto tupleInsp = NUdf::TTupleTypeInspector(th, subType)) {
+ PY_ENSURE(index < tupleInsp.GetElementsCount(),
+ "Index must be < " << tupleInsp.GetElementsCount()
+ << ", but got " << index);
+ auto* itemType = tupleInsp.GetElementType(index);
+ return castCtx->ValueBuilder->NewVariant(index, FromPyObject(castCtx, itemType, el1));
+ } else {
+ throw yexception() << "Cannot convert " << PyObjectRepr(value)
+ << " underlying Variant type is not a Tuple";
+ }
+ } else if (TryPyCast(el0, name)) {
+ if (auto structInsp = NUdf::TStructTypeInspector(th, subType)) {
+ ui32 index = structInsp.GetMemberIndex(name);
+ PY_ENSURE(index < structInsp.GetMembersCount(),
+ "Unknown member name: " << TStringBuf(name));
+ auto* itemType = structInsp.GetMemberType(index);
+ return castCtx->ValueBuilder->NewVariant(index, FromPyObject(castCtx, itemType, el1));
+ } else {
+ throw yexception() << "Cannot convert " << PyObjectRepr(value)
+ << " underlying Variant type is not a Struct";
+ }
+ } else {
+ throw yexception()
+ << "Expected first Tuple element to either be an int "
+ "or a str, but got " << Py_TYPE(el0)->tp_name;
+ }
+}
+
+} // namspace NPython