py_resource.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "py_resource.h"
  2. #include "py_cast.h"
  3. #include "py_errors.h"
  4. #include "py_gil.h"
  5. #include "py_utils.h"
  6. #include <yql/essentials/public/udf/udf_value.h>
  7. #include <yql/essentials/public/udf/udf_type_inspection.h>
  8. using namespace NKikimr;
  9. namespace NPython {
  10. namespace {
  11. void DestroyResourceCapsule(PyObject* obj) {
  12. if (auto* ptr = PyCapsule_GetPointer(obj, ResourceCapsuleName)) {
  13. delete reinterpret_cast<NUdf::TUnboxedValue*>(ptr);
  14. }
  15. }
  16. /////////////////////////////////////////////////////////////////////////////
  17. // TResource
  18. /////////////////////////////////////////////////////////////////////////////
  19. class TResource final: public NUdf::TBoxedValue
  20. {
  21. public:
  22. TResource(PyObject* value, const NUdf::TStringRef& tag)
  23. : Value_(value, TPyObjectPtr::ADD_REF), Tag_(tag)
  24. {
  25. }
  26. ~TResource() {
  27. TPyGilLocker lock;
  28. Value_.Reset();
  29. }
  30. private:
  31. NUdf::TStringRef GetResourceTag() const override {
  32. return Tag_;
  33. }
  34. void* GetResource() final {
  35. return Value_.Get();
  36. }
  37. TPyObjectPtr Value_;
  38. const NUdf::TStringRef Tag_;
  39. };
  40. } // namespace
  41. const char ResourceCapsuleName[] = "YqlResourceCapsule";
  42. TPyObjectPtr ToPyResource(
  43. const TPyCastContext::TPtr& ctx,
  44. const NUdf::TType* type,
  45. const NUdf::TUnboxedValuePod& value)
  46. {
  47. // TODO NILE-43
  48. #if false && UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 15)
  49. NUdf::TResourceTypeInspector inpector(*ctx->PyCtx->TypeInfoHelper, type);
  50. auto tag = inpector.GetTag();
  51. if (tag == ctx->PyCtx->ResourceTag) {
  52. PyObject* p = reinterpret_cast<PyObject*>(value.GetResource());
  53. return TPyObjectPtr(p, TPyObjectPtr::ADD_REF);
  54. }
  55. #else
  56. Y_UNUSED(type);
  57. if (value.GetResourceTag() == ctx->PyCtx->ResourceTag) {
  58. PyObject* p = reinterpret_cast<PyObject*>(value.GetResource());
  59. return TPyObjectPtr(p, TPyObjectPtr::ADD_REF);
  60. }
  61. #endif
  62. auto resource = MakeHolder<NUdf::TUnboxedValue>(value);
  63. return PyCapsule_New(resource.Release(), ResourceCapsuleName, &DestroyResourceCapsule);
  64. }
  65. NUdf::TUnboxedValue FromPyResource(
  66. const TPyCastContext::TPtr& ctx,
  67. const NUdf::TType* type, PyObject* value)
  68. {
  69. // TODO NILE-43
  70. #if false && UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 15)
  71. NUdf::TResourceTypeInspector inpector(*ctx->PyCtx->TypeInfoHelper, type);
  72. auto tag = inpector.GetTag();
  73. if (tag == ctx->PyCtx->ResourceTag) {
  74. return NUdf::TUnboxedValuePod(new TResource(value, ctx->PyCtx->ResourceTag));
  75. }
  76. if (PyCapsule_IsValid(value, ResourceCapsuleName)) {
  77. auto* resource = reinterpret_cast<NUdf::TUnboxedValue*>(PyCapsule_GetPointer(value, ResourceCapsuleName));
  78. auto valueTag = resource->GetResourceTag();
  79. if (valueTag != tag) {
  80. throw yexception() << "Mismatch of resource tag, expected: "
  81. << tag << ", got: " << valueTag;
  82. }
  83. return *resource;
  84. }
  85. throw yexception() << "Python object " << PyObjectRepr(value) \
  86. << " is not a valid resource with tag " << tag;
  87. #else
  88. Y_UNUSED(type);
  89. if (PyCapsule_CheckExact(value)) {
  90. if (!PyCapsule_IsValid(value, ResourceCapsuleName)) {
  91. throw yexception() << "Python object " << PyObjectRepr(value) << " is not a valid resource capsule";
  92. }
  93. return *reinterpret_cast<NUdf::TUnboxedValue*>(PyCapsule_GetPointer(value, ResourceCapsuleName));
  94. }
  95. return NUdf::TUnboxedValuePod(new TResource(value, ctx->PyCtx->ResourceTag));
  96. #endif
  97. }
  98. } // namspace NPython