123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- #include "py_cast.h"
- #include "py_errors.h"
- #include "py_gil.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>
- #include <yql/essentials/public/udf/udf_terminator.h>
- #include <util/generic/maybe.h>
- #include <util/string/builder.h>
- using namespace NKikimr;
- namespace NPython {
- namespace {
- //////////////////////////////////////////////////////////////////////////////
- // TLazyDictBase
- //////////////////////////////////////////////////////////////////////////////
- class TLazyDictBase: public NUdf::TBoxedValue
- {
- protected:
- class TIterator: public NUdf::TBoxedValue {
- public:
- TIterator(const TPyCastContext::TPtr& ctx, const NUdf::TType* type, TPyObjectPtr&& pyIter)
- : CastCtx_(ctx), ItemType_(type), PyIter_(std::move(pyIter))
- {}
- ~TIterator() {
- const TPyGilLocker lock;
- PyIter_.Reset();
- }
- private:
- bool Skip() override try {
- const TPyGilLocker lock;
- const TPyObjectPtr next(PyIter_Next(PyIter_.Get()));
- if (next) {
- return true;
- }
- if (PyErr_Occurred()) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return false;
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- bool Next(NUdf::TUnboxedValue& value) override try {
- const TPyGilLocker lock;
- const TPyObjectPtr next(PyIter_Next(PyIter_.Get()));
- if (next) {
- value = FromPyObject(CastCtx_, ItemType_, next.Get());
- return true;
- }
- if (PyErr_Occurred()) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return false;
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- bool NextPair(NUdf::TUnboxedValue& key, NUdf::TUnboxedValue& payload) override {
- payload = NUdf::TUnboxedValuePod::Void();
- return Next(key);
- }
- private:
- const TPyCastContext::TPtr CastCtx_;
- const NUdf::TType* ItemType_;
- TPyObjectPtr PyIter_;
- };
- class TPairIterator: public NUdf::TBoxedValue {
- public:
- TPairIterator(const TPyCastContext::TPtr& ctx, const NUdf::TType* keyType, const NUdf::TType* payType, TPyObjectPtr&& pyIter)
- : CastCtx_(ctx), KeyType_(keyType), PayType_(payType), PyIter_(std::move(pyIter))
- {}
- ~TPairIterator() {
- const TPyGilLocker lock;
- PyIter_.Reset();
- }
- private:
- bool Skip() override try {
- const TPyGilLocker lock;
- const TPyObjectPtr next(PyIter_Next(PyIter_.Get()));
- if (next) {
- return true;
- }
- if (PyErr_Occurred()) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return false;
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- bool NextPair(NUdf::TUnboxedValue& key, NUdf::TUnboxedValue& pay) override try {
- const TPyGilLocker lock;
- const TPyObjectPtr next(PyIter_Next(PyIter_.Get()));
- if (next) {
- key = FromPyObject(CastCtx_, KeyType_, PyTuple_GET_ITEM(next.Get(), 0));
- pay = FromPyObject(CastCtx_, PayType_, PyTuple_GET_ITEM(next.Get(), 1));
- return true;
- }
- if (PyErr_Occurred()) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return false;
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- private:
- const TPyCastContext::TPtr CastCtx_;
- const NUdf::TType* KeyType_;
- const NUdf::TType* PayType_;
- TPyObjectPtr PyIter_;
- };
- TLazyDictBase(const TPyCastContext::TPtr& castCtx, const NUdf::TType* itemType, PyObject* pyObject)
- : CastCtx_(castCtx), ItemType_(itemType), PyObject_(pyObject, TPyObjectPtr::AddRef())
- {}
- ~TLazyDictBase() {
- const TPyGilLocker lock;
- PyObject_.Reset();
- }
- bool HasDictItems() const override try {
- const TPyGilLocker lock;
- const auto has = PyObject_IsTrue(PyObject_.Get());
- if (has < 0) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return bool(has);
- }
- catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- const TPyCastContext::TPtr CastCtx_;
- const NUdf::TType* ItemType_;
- TPyObjectPtr PyObject_;
- };
- //////////////////////////////////////////////////////////////////////////////
- // TLazyMapping
- //////////////////////////////////////////////////////////////////////////////
- class TLazyMapping: public TLazyDictBase
- {
- public:
- TLazyMapping(const TPyCastContext::TPtr& ctx, const NUdf::TType* keyType, const NUdf::TType* payType, PyObject* dict)
- : TLazyDictBase(ctx, keyType, dict), PayType_(payType)
- {}
- private:
- bool IsSortedDict() const override { return false; }
- ui64 GetDictLength() const override try {
- const TPyGilLocker lock;
- const auto len = PyMapping_Size(PyObject_.Get());
- if (len < 0) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return ui64(len);
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetKeysIterator() const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyList = PyMapping_Keys(PyObject_.Get())) {
- if (TPyObjectPtr pyIter = PyObject_GetIter(pyList.Get())) {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, ItemType_, std::move(pyIter)));
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetPayloadsIterator() const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyList = PyMapping_Values(PyObject_.Get())) {
- if (TPyObjectPtr pyIter = PyObject_GetIter(pyList.Get())) {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, PayType_, std::move(pyIter)));
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetDictIterator() const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyList = PyMapping_Items(PyObject_.Get())) {
- if (TPyObjectPtr pyIter = PyObject_GetIter(pyList.Get())) {
- return NUdf::TUnboxedValuePod(new TPairIterator(CastCtx_, ItemType_, PayType_, std::move(pyIter)));
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue Lookup(const NUdf::TUnboxedValuePod& key) const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyKey = ToPyObject(CastCtx_, ItemType_, key)) {
- if (const auto item = PyObject_GetItem(PyObject_.Get(), pyKey.Get())) {
- return FromPyObject(CastCtx_, PayType_, item).Release().MakeOptional();
- }
- if (PyErr_Occurred()) {
- PyErr_Clear();
- }
- return NUdf::TUnboxedValue();
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- bool Contains(const NUdf::TUnboxedValuePod& key) const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyKey = ToPyObject(CastCtx_, ItemType_, key)) {
- const auto map = PyObject_.Get();
- const auto has = map->ob_type->tp_as_sequence && map->ob_type->tp_as_sequence->sq_contains ?
- (map->ob_type->tp_as_sequence->sq_contains)(map, pyKey.Get()) :
- PyMapping_HasKey(map, pyKey.Get());
- if (has >= 0) {
- return bool(has);
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- private:
- const NUdf::TType* PayType_;
- };
- //////////////////////////////////////////////////////////////////////////////
- // TLazyDict
- //////////////////////////////////////////////////////////////////////////////
- class TLazyDict: public TLazyDictBase
- {
- public:
- TLazyDict(const TPyCastContext::TPtr& ctx, const NUdf::TType* keyType, const NUdf::TType* payType, PyObject* dict)
- : TLazyDictBase(ctx, keyType, dict), PayType_(payType)
- {}
- private:
- bool IsSortedDict() const override { return false; }
- ui64 GetDictLength() const override try {
- const TPyGilLocker lock;
- const auto len = PyDict_Size(PyObject_.Get());
- if (len < 0) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return ui64(len);
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetKeysIterator() const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyList = PyDict_Keys(PyObject_.Get())) {
- if (TPyObjectPtr pyIter = PyObject_GetIter(pyList.Get())) {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, ItemType_, std::move(pyIter)));
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetPayloadsIterator() const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyList = PyDict_Values(PyObject_.Get())) {
- if (TPyObjectPtr pyIter = PyObject_GetIter(pyList.Get())) {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, PayType_, std::move(pyIter)));
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetDictIterator() const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyList = PyDict_Items(PyObject_.Get())) {
- if (TPyObjectPtr pyIter = PyObject_GetIter(pyList.Get())) {
- return NUdf::TUnboxedValuePod(new TPairIterator(CastCtx_, ItemType_, PayType_, std::move(pyIter)));
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue Lookup(const NUdf::TUnboxedValuePod& key) const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyKey = ToPyObject(CastCtx_, ItemType_, key)) {
- if (const auto item = PyDict_GetItem(PyObject_.Get(), pyKey.Get())) {
- return FromPyObject(CastCtx_, PayType_, item).Release().MakeOptional();
- } else if (!PyErr_Occurred()) {
- return NUdf::TUnboxedValue();
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- bool Contains(const NUdf::TUnboxedValuePod& key) const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyKey = ToPyObject(CastCtx_, ItemType_, key)) {
- const auto has = PyDict_Contains(PyObject_.Get(), pyKey.Get());
- if (has >= 0) {
- return bool(has);
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- private:
- const NUdf::TType* PayType_;
- };
- //////////////////////////////////////////////////////////////////////////////
- // TLazySet
- //////////////////////////////////////////////////////////////////////////////
- class TLazySet: public TLazyDictBase
- {
- public:
- TLazySet(const TPyCastContext::TPtr& ctx, const NUdf::TType* itemType, PyObject* set)
- : TLazyDictBase(ctx, itemType, set)
- {}
- private:
- bool IsSortedDict() const override { return false; }
- ui64 GetDictLength() const override try {
- const TPyGilLocker lock;
- const auto len = PySet_Size(PyObject_.Get());
- if (len < 0) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return ui64(len);
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue Lookup(const NUdf::TUnboxedValuePod& key) const override {
- return Contains(key) ? NUdf::TUnboxedValuePod::Void() : NUdf::TUnboxedValuePod();
- }
- bool Contains(const NUdf::TUnboxedValuePod& key) const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyKey = ToPyObject(CastCtx_, ItemType_, key)) {
- const auto has = PySet_Contains(PyObject_.Get(), pyKey.Get());
- if (has >= 0) {
- return bool(has);
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetKeysIterator() const override try {
- const TPyGilLocker lock;
- if (TPyObjectPtr pyIter = PyObject_GetIter(PyObject_.Get())) {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, ItemType_, std::move(pyIter)));
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetPayloadsIterator() const override {
- return GetKeysIterator();
- }
- NUdf::TUnboxedValue GetDictIterator() const override {
- return GetKeysIterator();
- }
- NUdf::TUnboxedValue GetListIterator() const override {
- return GetKeysIterator();
- }
- ui64 GetListLength() const override {
- return GetDictLength();
- }
- bool HasListItems() const override {
- return HasDictItems();
- }
- bool HasFastListLength() const override {
- return true;
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- // TLazySequenceAsSet
- //////////////////////////////////////////////////////////////////////////////
- class TLazySequenceAsSet: public TLazyDictBase
- {
- public:
- TLazySequenceAsSet(const TPyCastContext::TPtr& ctx, const NUdf::TType* keyType, PyObject* sequence)
- : TLazyDictBase(ctx, keyType, sequence)
- {}
- private:
- bool IsSortedDict() const override { return false; }
- ui64 GetDictLength() const override try {
- const TPyGilLocker lock;
- const auto len = PySequence_Size(PyObject_.Get());
- if (len < 0) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- return ui64(len);
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue Lookup(const NUdf::TUnboxedValuePod& key) const override {
- return Contains(key) ? NUdf::TUnboxedValuePod::Void() : NUdf::TUnboxedValuePod();
- }
- bool Contains(const NUdf::TUnboxedValuePod& key) const override try {
- const TPyGilLocker lock;
- if (const TPyObjectPtr pyKey = ToPyObject(CastCtx_, ItemType_, key)) {
- const auto has = PySequence_Contains(PyObject_.Get(), pyKey.Get());
- if (has >= 0) {
- return bool(has);
- }
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetKeysIterator() const override try {
- const TPyGilLocker lock;
- if (TPyObjectPtr pyIter = PyObject_GetIter(PyObject_.Get())) {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, ItemType_, std::move(pyIter)));
- }
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- NUdf::TUnboxedValue GetPayloadsIterator() const override {
- return GetKeysIterator();
- }
- NUdf::TUnboxedValue GetDictIterator() const override {
- return GetKeysIterator();
- }
- NUdf::TUnboxedValue GetListIterator() const override {
- return GetKeysIterator();
- }
- ui64 GetListLength() const override {
- return GetDictLength();
- }
- bool HasListItems() const override {
- return HasDictItems();
- }
- bool HasFastListLength() const override {
- return true;
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- // TLazySequenceAsDict
- //////////////////////////////////////////////////////////////////////////////
- template<typename KeyType>
- class TLazySequenceAsDict: public NUdf::TBoxedValue
- {
- private:
- class TKeyIterator: public NUdf::TBoxedValue {
- public:
- TKeyIterator(Py_ssize_t size)
- : Size(size), Index(0)
- {}
- private:
- bool Skip() override {
- if (Index >= Size)
- return false;
- ++Index;
- return true;
- }
- bool Next(NUdf::TUnboxedValue& value) override {
- if (Index >= Size)
- return false;
- value = NUdf::TUnboxedValuePod(KeyType(Index++));
- return true;
- }
- private:
- const Py_ssize_t Size;
- Py_ssize_t Index;
- };
- class TIterator: public NUdf::TBoxedValue {
- public:
- TIterator(const TPyCastContext::TPtr& ctx, const NUdf::TType* itemType, Py_ssize_t size, const TPyObjectPtr& pySeq)
- : CastCtx_(ctx), ItemType_(itemType), PySeq_(pySeq), Size(size), Index(0)
- {}
- ~TIterator() {
- const TPyGilLocker lock;
- PySeq_.Reset();
- }
- private:
- bool Skip() override {
- if (Index >= Size)
- return false;
- ++Index;
- return true;
- }
- bool Next(NUdf::TUnboxedValue& value) override try {
- if (Index >= Size)
- return false;
- const TPyGilLocker lock;
- value = FromPyObject(CastCtx_, ItemType_, PySequence_Fast_GET_ITEM(PySeq_.Get(), Index++));
- return true;
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- bool NextPair(NUdf::TUnboxedValue& key, NUdf::TUnboxedValue& pay) override try {
- if (Index >= Size)
- return false;
- const TPyGilLocker lock;
- key = NUdf::TUnboxedValuePod(KeyType(Index));
- pay = FromPyObject(CastCtx_, ItemType_, PySequence_Fast_GET_ITEM(PySeq_.Get(), Index++));
- return true;
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- private:
- const TPyCastContext::TPtr CastCtx_;
- const NUdf::TType* ItemType_;
- TPyObjectPtr PySeq_;
- const Py_ssize_t Size;
- Py_ssize_t Index;
- };
- public:
- TLazySequenceAsDict(const TPyCastContext::TPtr& ctx, const NUdf::TType* itemType, TPyObjectPtr&& sequence, Py_ssize_t size)
- : CastCtx_(ctx), ItemType_(itemType), Size(size), PySeq_(std::move(sequence))
- {}
- ~TLazySequenceAsDict()
- {
- const TPyGilLocker lock;
- PySeq_.Reset();
- }
- private:
- bool IsSortedDict() const override { return true; }
- bool HasDictItems() const override {
- return Size > 0;
- }
- ui64 GetDictLength() const override {
- return Size;
- }
- NUdf::TUnboxedValue Lookup(const NUdf::TUnboxedValuePod& key) const override {
- const Py_ssize_t index = key.Get<KeyType>();
- if (index >= -Size && index < Size) try {
- const TPyGilLocker lock;
- if (const auto item = PySequence_Fast_GET_ITEM(PySeq_.Get(), index >= 0 ? index : Size + index)) {
- return FromPyObject(CastCtx_, ItemType_, item).Release().MakeOptional();
- } else if (PyErr_Occurred()) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- } catch (const yexception& e) {
- UdfTerminate((TStringBuilder() << CastCtx_->PyCtx->Pos << e.what()).data());
- }
- return NUdf::TUnboxedValue();
- }
- bool Contains(const NUdf::TUnboxedValuePod& key) const override {
- const Py_ssize_t index = key.Get<KeyType>();
- return index >= -Size && index < Size;
- }
- NUdf::TUnboxedValue GetKeysIterator() const override {
- return NUdf::TUnboxedValuePod(new TKeyIterator(Size));
- }
- NUdf::TUnboxedValue GetPayloadsIterator() const override {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, ItemType_, Size, PySeq_));
- }
- NUdf::TUnboxedValue GetDictIterator() const override {
- return NUdf::TUnboxedValuePod(new TIterator(CastCtx_, ItemType_, Size, PySeq_));
- }
- const TPyCastContext::TPtr CastCtx_;
- const NUdf::TType* ItemType_;
- const Py_ssize_t Size;
- TPyObjectPtr PySeq_;
- };
- } // namspace
- NUdf::TUnboxedValue FromPyDict(
- const TPyCastContext::TPtr& castCtx,
- const NUdf::TType* keyType,
- const NUdf::TType* payType,
- PyObject* dict)
- {
- return NUdf::TUnboxedValuePod(new TLazyDict(castCtx, keyType, payType, dict));
- }
- NUdf::TUnboxedValue FromPyMapping(
- const TPyCastContext::TPtr& castCtx,
- const NUdf::TType* keyType,
- const NUdf::TType* payType,
- PyObject* map)
- {
- return NUdf::TUnboxedValuePod(new TLazyMapping(castCtx, keyType, payType, map));
- }
- NUdf::TUnboxedValue FromPySet(
- const TPyCastContext::TPtr& castCtx,
- const NUdf::TType* itemType,
- PyObject* set)
- {
- return NUdf::TUnboxedValuePod(new TLazySet(castCtx, itemType, set));
- }
- NUdf::TUnboxedValue FromPySequence(
- const TPyCastContext::TPtr& castCtx,
- const NUdf::TType* keyType,
- PyObject* set)
- {
- return NUdf::TUnboxedValuePod(new TLazySequenceAsSet(castCtx, keyType, set));
- }
- NUdf::TUnboxedValue FromPySequence(
- const TPyCastContext::TPtr& castCtx,
- const NUdf::TType* itemType,
- const NUdf::TDataTypeId keyType,
- PyObject* sequence)
- {
- if (TPyObjectPtr fast = PySequence_Fast(sequence, "Can't get fast sequence.")) {
- const auto size = PySequence_Fast_GET_SIZE(fast.Get());
- if (size >= 0) {
- switch (keyType) {
- #define MAKE_PRIMITIVE_TYPE_SIZE(type) \
- case NUdf::TDataType<type>::Id: \
- return NUdf::TUnboxedValuePod(new TLazySequenceAsDict<type>(castCtx, itemType, std::move(fast), size));
- INTEGRAL_VALUE_TYPES(MAKE_PRIMITIVE_TYPE_SIZE)
- #undef MAKE_PRIMITIVE_TYPE_SIZE
- }
- Y_ABORT("Invalid key type.");
- }
- }
- UdfTerminate((TStringBuilder() << castCtx->PyCtx->Pos << GetLastErrorAsString()).data());
- }
- } // namespace NPython
|