py_dict_ut.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. #include "ut3/py_test_engine.h"
  2. #include <yql/essentials/public/udf/udf_ut_helpers.h>
  3. #include <library/cpp/testing/unittest/registar.h>
  4. using namespace NPython;
  5. Y_UNIT_TEST_SUITE(TPyDictTest) {
  6. Y_UNIT_TEST(FromPyEmptyDict) {
  7. TPythonTestEngine engine;
  8. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  9. "def Test(): return {}",
  10. [](const NUdf::TUnboxedValuePod& value) {
  11. UNIT_ASSERT(value);
  12. UNIT_ASSERT(value.IsBoxed());
  13. UNIT_ASSERT(!value.HasDictItems());
  14. UNIT_ASSERT_EQUAL(value.GetDictLength(), 0);
  15. });
  16. }
  17. Y_UNIT_TEST(FromPyDict_Length) {
  18. TPythonTestEngine engine;
  19. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  20. "def Test(): return {1: 'one', 3: 'three', 2: 'two'}",
  21. [](const NUdf::TUnboxedValuePod& value) {
  22. UNIT_ASSERT(value);
  23. UNIT_ASSERT(value.IsBoxed());
  24. UNIT_ASSERT(value.HasDictItems());
  25. UNIT_ASSERT(!value.IsSortedDict());
  26. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  27. });
  28. }
  29. Y_UNIT_TEST(FromPyDict_Lookup) {
  30. TPythonTestEngine engine;
  31. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  32. "def Test(): return {1: 'one', 3: 'three', 2: 'two'}",
  33. [](const NUdf::TUnboxedValuePod& value) {
  34. const auto v1 = value.Lookup(NUdf::TUnboxedValuePod(ui32(1)));
  35. UNIT_ASSERT_EQUAL(v1.AsStringRef(), "one");
  36. const auto v2 = value.Lookup(NUdf::TUnboxedValuePod(ui32(2)));
  37. UNIT_ASSERT_EQUAL(v2.AsStringRef(), "two");
  38. const auto v3 = value.Lookup(NUdf::TUnboxedValuePod(ui32(3)));
  39. UNIT_ASSERT_EQUAL(v3.AsStringRef(), "three");
  40. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(ui32(0))));
  41. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(ui32(4))));
  42. });
  43. }
  44. Y_UNIT_TEST(FromPyDict_Contains) {
  45. TPythonTestEngine engine;
  46. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  47. "def Test(): return {1: 'one', 3: 'three', 2: 'two'}",
  48. [](const NUdf::TUnboxedValuePod& value) {
  49. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(ui32(0))));
  50. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(ui32(1))));
  51. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(ui32(2))));
  52. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(ui32(3))));
  53. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(ui32(4))));
  54. });
  55. }
  56. Y_UNIT_TEST(FromPyDict_Items) {
  57. TPythonTestEngine engine;
  58. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  59. "def Test(): return {1: 'one', 3: 'three', 2: 'two'}",
  60. [](const NUdf::TUnboxedValuePod& value) {
  61. std::map<ui32, TString> items;
  62. const auto it = value.GetDictIterator();
  63. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  64. items.emplace(key.Get<ui32>(), payload.AsStringRef());
  65. }
  66. UNIT_ASSERT_EQUAL(items.size(), 3);
  67. UNIT_ASSERT_EQUAL(items[1], "one");
  68. UNIT_ASSERT_EQUAL(items[2], "two");
  69. UNIT_ASSERT_EQUAL(items[3], "three");
  70. });
  71. }
  72. Y_UNIT_TEST(FromPyDict_Keys) {
  73. TPythonTestEngine engine;
  74. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  75. "def Test(): return {1: 'one', 3: 'three', 2: 'two'}",
  76. [](const NUdf::TUnboxedValuePod& value) {
  77. std::vector<ui32> items;
  78. const auto it = value.GetKeysIterator();
  79. for (NUdf::TUnboxedValue key; it.Next(key);) {
  80. items.emplace_back(key.Get<ui32>());
  81. }
  82. UNIT_ASSERT_EQUAL(items.size(), 3);
  83. std::sort(items.begin(), items.end());
  84. UNIT_ASSERT_EQUAL(items[0], 1U);
  85. UNIT_ASSERT_EQUAL(items[1], 2U);
  86. UNIT_ASSERT_EQUAL(items[2], 3U);
  87. });
  88. }
  89. Y_UNIT_TEST(FromPyDict_Values) {
  90. TPythonTestEngine engine;
  91. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  92. "def Test(): return {1: 'one', 3: 'three', 2: 'two'}",
  93. [](const NUdf::TUnboxedValuePod& value) {
  94. std::vector<TString> items;
  95. const auto it = value.GetPayloadsIterator();
  96. for (NUdf::TUnboxedValue payload; it.Next(payload);) {
  97. items.emplace_back(payload.AsStringRef());
  98. }
  99. UNIT_ASSERT_EQUAL(items.size(), 3);
  100. std::sort(items.begin(), items.end());
  101. UNIT_ASSERT_EQUAL(items[0], "one");
  102. UNIT_ASSERT_EQUAL(items[1], "three");
  103. UNIT_ASSERT_EQUAL(items[2], "two");
  104. });
  105. }
  106. Y_UNIT_TEST(FromPyList_Length) {
  107. TPythonTestEngine engine;
  108. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  109. "def Test(): return ['one', 'two', 'three']",
  110. [](const NUdf::TUnboxedValuePod& value) {
  111. UNIT_ASSERT(value);
  112. UNIT_ASSERT(value.IsBoxed());
  113. UNIT_ASSERT(value.HasDictItems());
  114. UNIT_ASSERT(value.IsSortedDict());
  115. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  116. });
  117. }
  118. Y_UNIT_TEST(FromPyTuple_Lookup) {
  119. TPythonTestEngine engine;
  120. engine.ToMiniKQL<NUdf::TDict<i32, char*>>(
  121. "def Test(): return ('one', 'two', 'three')",
  122. [](const NUdf::TUnboxedValuePod& value) {
  123. const auto v1 = value.Lookup(NUdf::TUnboxedValuePod(i32(0)));
  124. UNIT_ASSERT_EQUAL(v1.AsStringRef(), "one");
  125. const auto v2 = value.Lookup(NUdf::TUnboxedValuePod(i32(1)));
  126. UNIT_ASSERT_EQUAL(v2.AsStringRef(), "two");
  127. const auto v3 = value.Lookup(NUdf::TUnboxedValuePod(i32(2)));
  128. UNIT_ASSERT_EQUAL(v3.AsStringRef(), "three");
  129. const auto v4 = value.Lookup(NUdf::TUnboxedValuePod(i32(-1)));
  130. UNIT_ASSERT_EQUAL(v4.AsStringRef(), "three");
  131. const auto v5 = value.Lookup(NUdf::TUnboxedValuePod(i32(-2)));
  132. UNIT_ASSERT_EQUAL(v5.AsStringRef(), "two");
  133. const auto v6 = value.Lookup(NUdf::TUnboxedValuePod(i32(-3)));
  134. UNIT_ASSERT_EQUAL(v6.AsStringRef(), "one");
  135. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(i32(3))));
  136. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(i32(-4))));
  137. });
  138. }
  139. Y_UNIT_TEST(FromPyList_Contains) {
  140. TPythonTestEngine engine;
  141. engine.ToMiniKQL<NUdf::TDict<i16, char*>>(
  142. "def Test(): return ['one', 'two', 'three']",
  143. [](const NUdf::TUnboxedValuePod& value) {
  144. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i16(0))));
  145. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i16(1))));
  146. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i16(2))));
  147. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(i16(3))));
  148. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i16(-1))));
  149. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i16(-2))));
  150. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i16(-3))));
  151. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(i16(-4))));
  152. });
  153. }
  154. Y_UNIT_TEST(FromPyTuple_Items) {
  155. TPythonTestEngine engine;
  156. engine.ToMiniKQL<NUdf::TDict<ui16, char*>>(
  157. "def Test(): return ('one', 'two', 'three')",
  158. [](const NUdf::TUnboxedValuePod& value) {
  159. std::vector<std::pair<ui16, TString>> items;
  160. const auto it = value.GetDictIterator();
  161. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  162. items.emplace_back(key.Get<ui16>(), payload.AsStringRef());
  163. }
  164. UNIT_ASSERT_EQUAL(items.size(), 3U);
  165. UNIT_ASSERT_EQUAL(items[0].first, 0);
  166. UNIT_ASSERT_EQUAL(items[1].first, 1);
  167. UNIT_ASSERT_EQUAL(items[2].first, 2);
  168. UNIT_ASSERT_EQUAL(items[0].second, "one");
  169. UNIT_ASSERT_EQUAL(items[1].second, "two");
  170. UNIT_ASSERT_EQUAL(items[2].second, "three");
  171. });
  172. }
  173. Y_UNIT_TEST(FromPyList_Keys) {
  174. TPythonTestEngine engine;
  175. engine.ToMiniKQL<NUdf::TDict<i64, char*>>(
  176. "def Test(): return ['one', 'two', 'three']",
  177. [](const NUdf::TUnboxedValuePod& value) {
  178. std::vector<i64> items;
  179. const auto it = value.GetKeysIterator();
  180. for (NUdf::TUnboxedValue key; it.Next(key);) {
  181. items.emplace_back(key.Get<i64>());
  182. }
  183. UNIT_ASSERT_EQUAL(items.size(), 3);
  184. UNIT_ASSERT_EQUAL(items[0], 0);
  185. UNIT_ASSERT_EQUAL(items[1], 1);
  186. UNIT_ASSERT_EQUAL(items[2], 2);
  187. });
  188. }
  189. Y_UNIT_TEST(FromPyTuple_Values) {
  190. TPythonTestEngine engine;
  191. engine.ToMiniKQL<NUdf::TDict<ui64, char*>>(
  192. "def Test(): return ('one', 'two', 'three')",
  193. [](const NUdf::TUnboxedValuePod& value) {
  194. std::vector<TString> items;
  195. const auto it = value.GetPayloadsIterator();
  196. for (NUdf::TUnboxedValue payload; it.Next(payload);) {
  197. items.emplace_back(payload.AsStringRef());
  198. }
  199. UNIT_ASSERT_EQUAL(items.size(), 3);
  200. UNIT_ASSERT_EQUAL(items[0], "one");
  201. UNIT_ASSERT_EQUAL(items[1], "two");
  202. UNIT_ASSERT_EQUAL(items[2], "three");
  203. });
  204. }
  205. Y_UNIT_TEST(ToPyEmptyDict) {
  206. TPythonTestEngine engine;
  207. engine.ToPython<NUdf::TDict<ui8, ui32>>(
  208. [](const TType* type, const NUdf::IValueBuilder& vb) {
  209. Y_UNUSED(type);
  210. return vb.NewDict(type, NUdf::TDictFlags::Hashed)->Build();
  211. },
  212. "def Test(value):\n"
  213. " assert not value\n"
  214. " assert len(value) == 0\n"
  215. );
  216. }
  217. Y_UNIT_TEST(ToPyDict) {
  218. TPythonTestEngine engine;
  219. engine.ToPython<NUdf::TDict<int, double>>(
  220. [](const TType* type, const NUdf::IValueBuilder& vb) {
  221. return vb.NewDict(type, NUdf::TDictFlags::Hashed)->
  222. Add(NUdf::TUnboxedValuePod((int) 1), NUdf::TUnboxedValuePod((double) 0.1))
  223. .Add(NUdf::TUnboxedValuePod((int) 2), NUdf::TUnboxedValuePod((double) 0.2))
  224. .Add(NUdf::TUnboxedValuePod((int) 3), NUdf::TUnboxedValuePod((double) 0.3))
  225. .Build();
  226. },
  227. "def Test(value):\n"
  228. " assert value\n"
  229. " assert len(value) == 3\n"
  230. " assert iter(value) is not None\n"
  231. " assert 2 in value\n"
  232. " assert 0 not in value\n"
  233. " assert set(iter(value)) == set([1, 2, 3])\n"
  234. " assert value[2] == 0.2\n"
  235. " assert value.get(0, 0.7) == 0.7\n"
  236. " assert value.get(3, 0.7) == 0.3\n"
  237. " assert sorted(value.keys()) == [1, 2, 3]\n"
  238. " assert sorted(value.items()) == [(1, 0.1), (2, 0.2), (3, 0.3)]\n"
  239. " assert sorted(value.values()) == [0.1, 0.2, 0.3]\n"
  240. #if PY_MAJOR_VERSION < 3
  241. " assert all(isinstance(k, int) for k in value.iterkeys())\n"
  242. " assert all(isinstance(v, float) for v in value.itervalues())\n"
  243. " assert all(isinstance(k, int) and isinstance(v, float) for k,v in value.iteritems())\n"
  244. #endif
  245. );
  246. }
  247. Y_UNIT_TEST(ToPyDictWrongKey) {
  248. TPythonTestEngine engine;
  249. engine.ToPython<NUdf::TDict<int, double>>(
  250. [](const TType* type, const NUdf::IValueBuilder& vb) {
  251. return vb.NewDict(type, NUdf::TDictFlags::Hashed)->
  252. Add(NUdf::TUnboxedValuePod((int) 1), NUdf::TUnboxedValuePod((double) 0.1))
  253. .Add(NUdf::TUnboxedValuePod((int) 2), NUdf::TUnboxedValuePod((double) 0.2))
  254. .Add(NUdf::TUnboxedValuePod((int) 3), NUdf::TUnboxedValuePod((double) 0.3))
  255. .Build();
  256. },
  257. "def Test(value):\n"
  258. " try:\n"
  259. " print(value[0])\n"
  260. " except KeyError:\n"
  261. " pass\n"
  262. " else:\n"
  263. " assert False\n"
  264. );
  265. }
  266. Y_UNIT_TEST(FromPyEmptySet) {
  267. TPythonTestEngine engine;
  268. engine.ToMiniKQL<NUdf::TDict<ui32, void>>(
  269. "def Test(): return set([])",
  270. [](const NUdf::TUnboxedValuePod& value) {
  271. UNIT_ASSERT(value);
  272. UNIT_ASSERT(value.IsBoxed());
  273. UNIT_ASSERT(!value.HasDictItems());
  274. UNIT_ASSERT_EQUAL(value.GetDictLength(), 0);
  275. });
  276. }
  277. Y_UNIT_TEST(FromPySet) {
  278. TPythonTestEngine engine;
  279. engine.ToMiniKQL<NUdf::TDict<char*, void>>(
  280. "def Test(): return set(['one', 'two', 'three'])",
  281. [](const NUdf::TUnboxedValuePod& value) {
  282. UNIT_ASSERT(value);
  283. UNIT_ASSERT(value.IsBoxed());
  284. UNIT_ASSERT(value.HasDictItems());
  285. UNIT_ASSERT(!value.IsSortedDict());
  286. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  287. std::set<TString> set;
  288. const auto it = value.GetKeysIterator();
  289. for (NUdf::TUnboxedValue key; it.Next(key);) {
  290. set.emplace(key.AsStringRef());
  291. }
  292. UNIT_ASSERT_EQUAL(set.size(), 3);
  293. UNIT_ASSERT(set.count("one"));
  294. UNIT_ASSERT(set.count("two"));
  295. UNIT_ASSERT(set.count("three"));
  296. });
  297. }
  298. Y_UNIT_TEST(FromPySet_Contains) {
  299. TPythonTestEngine engine;
  300. engine.ToMiniKQL<NUdf::TDict<char*, void>>(
  301. "def Test(): return {b'one', b'two', b'three'}",
  302. [](const NUdf::TUnboxedValuePod& value) {
  303. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod::Embedded("one")));
  304. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod::Embedded("two")));
  305. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod::Embedded("three")));
  306. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod::Embedded("zero")));
  307. });
  308. }
  309. Y_UNIT_TEST(ToPyEmptySet) {
  310. TPythonTestEngine engine;
  311. engine.ToPython<NUdf::TDict<ui8, void>>(
  312. [](const TType* type, const NUdf::IValueBuilder& vb) {
  313. Y_UNUSED(type);
  314. return vb.NewDict(type, NUdf::TDictFlags::Hashed)->Build();
  315. },
  316. "def Test(value):\n"
  317. " assert not value\n"
  318. " assert len(value) == 0\n"
  319. );
  320. }
  321. Y_UNIT_TEST(ToPySet) {
  322. TPythonTestEngine engine;
  323. engine.ToPython<NUdf::TDict<ui8, void>>(
  324. [](const TType* type, const NUdf::IValueBuilder& vb) {
  325. return vb.NewDict(type, NUdf::TDictFlags::Hashed)->
  326. Add(NUdf::TUnboxedValuePod((ui8) 1), NUdf::TUnboxedValuePod::Void())
  327. .Add(NUdf::TUnboxedValuePod((ui8) 2), NUdf::TUnboxedValuePod::Void())
  328. .Add(NUdf::TUnboxedValuePod((ui8) 3), NUdf::TUnboxedValuePod::Void())
  329. .Build();
  330. },
  331. "def Test(value):\n"
  332. " assert len(value) == 3\n"
  333. " assert all(isinstance(k, int) for k in iter(value))\n"
  334. " assert all(i in value for i in [1, 2, 3])\n");
  335. }
  336. Y_UNIT_TEST(FromPyMultiDict) {
  337. TPythonTestEngine engine;
  338. engine.ToMiniKQL<NUdf::TDict<ui32, NUdf::TListType<char*>>>(
  339. "def Test(): return {1: ['one', 'two'], 3: ['three']}",
  340. [](const NUdf::TUnboxedValuePod& value) {
  341. UNIT_ASSERT(value);
  342. UNIT_ASSERT(value.IsBoxed());
  343. UNIT_ASSERT_EQUAL(value.GetDictLength(), 2);
  344. std::unordered_map<ui32, std::vector<TString>> map;
  345. const auto dictIt = value.GetDictIterator();
  346. for (NUdf::TUnboxedValue key, payload; dictIt.NextPair(key, payload);) {
  347. auto& val = map[key.Get<ui32>()];
  348. const auto listIt = payload.GetListIterator();
  349. for (NUdf::TUnboxedValue listItem; listIt.Next(listItem);) {
  350. val.emplace_back(listItem.AsStringRef());
  351. }
  352. }
  353. UNIT_ASSERT_EQUAL(map.size(), 2);
  354. auto it = map.find(1);
  355. UNIT_ASSERT(it != map.end());
  356. UNIT_ASSERT_EQUAL(it->second.size(), 2);
  357. UNIT_ASSERT_EQUAL(it->second[0], "one");
  358. UNIT_ASSERT_EQUAL(it->second[1], "two");
  359. it = map.find(3);
  360. UNIT_ASSERT(it != map.end());
  361. UNIT_ASSERT_EQUAL(it->second.size(), 1);
  362. UNIT_ASSERT_EQUAL(it->second[0], "three");
  363. });
  364. }
  365. Y_UNIT_TEST(ToPyMultiDict) {
  366. TPythonTestEngine engine;
  367. engine.ToPython<NUdf::TDict<ui8, NUdf::TListType<NUdf::TUtf8>>>(
  368. [](const TType* type, const NUdf::IValueBuilder& vb) {
  369. ui32 flags = NUdf::TDictFlags::Hashed | NUdf::TDictFlags::Multi;
  370. return vb.NewDict(type, flags)->
  371. Add(NUdf::TUnboxedValuePod((ui8) 1), vb.NewString("one"))
  372. .Add(NUdf::TUnboxedValuePod((ui8) 1), vb.NewString("two"))
  373. .Add(NUdf::TUnboxedValuePod((ui8) 3), vb.NewString("three"))
  374. .Build();
  375. },
  376. "def Test(value):\n"
  377. " assert len(value) == 2\n"
  378. " assert 1 in value\n"
  379. " assert 3 in value\n"
  380. " assert len(value[1]) == 2\n"
  381. " assert 'one' in value[1]\n"
  382. " assert 'two' in value[1]\n"
  383. " assert list(value[3]) == ['three']\n");
  384. }
  385. Y_UNIT_TEST(ToPyAndBackDictAsIs) {
  386. TPythonTestEngine engine;
  387. engine.ToPythonAndBack<NUdf::TDict<i32, double>>(
  388. [](const TType* type, const NUdf::IValueBuilder& vb) {
  389. return vb.NewDict(type, NUdf::TDictFlags::Sorted)->
  390. Add(NUdf::TUnboxedValuePod((i32) 1), NUdf::TUnboxedValuePod((double) 0.1))
  391. .Add(NUdf::TUnboxedValuePod((i32) 2), NUdf::TUnboxedValuePod((double) 0.2))
  392. .Add(NUdf::TUnboxedValuePod((i32) 3), NUdf::TUnboxedValuePod((double) 0.3))
  393. .Build();
  394. },
  395. "def Test(value): return value",
  396. [](const NUdf::TUnboxedValuePod& value) {
  397. UNIT_ASSERT(value.HasDictItems());
  398. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  399. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod((i32) 0)));
  400. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod((i32) 3)));
  401. UNIT_ASSERT_EQUAL(value.Lookup(NUdf::TUnboxedValuePod((i32) 2)).Get<double>(), 0.2);
  402. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod((i32) 4)));
  403. std::vector<std::pair<i32, double>> items;
  404. const auto it = value.GetDictIterator();
  405. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  406. items.emplace_back(key.Get<i32>(), payload.Get<double>());
  407. }
  408. UNIT_ASSERT_EQUAL(items.size(), 3);
  409. UNIT_ASSERT_EQUAL(items[0].first, 1);
  410. UNIT_ASSERT_EQUAL(items[1].first, 2);
  411. UNIT_ASSERT_EQUAL(items[2].first, 3);
  412. UNIT_ASSERT_EQUAL(items[0].second, 0.1);
  413. UNIT_ASSERT_EQUAL(items[1].second, 0.2);
  414. UNIT_ASSERT_EQUAL(items[2].second, 0.3);
  415. std::vector<i32> keys;
  416. const auto kit = value.GetKeysIterator();
  417. for (NUdf::TUnboxedValue key; kit.Next(key);) {
  418. keys.emplace_back(key.Get<i32>());
  419. }
  420. UNIT_ASSERT_EQUAL(keys.size(), 3);
  421. UNIT_ASSERT_EQUAL(keys[0], 1);
  422. UNIT_ASSERT_EQUAL(keys[1], 2);
  423. UNIT_ASSERT_EQUAL(keys[2], 3);
  424. std::vector<double> values;
  425. const auto pit = value.GetPayloadsIterator();
  426. for (NUdf::TUnboxedValue payload; pit.Next(payload);) {
  427. values.emplace_back(payload.Get<double>());
  428. }
  429. UNIT_ASSERT_EQUAL(values.size(), 3);
  430. UNIT_ASSERT_EQUAL(values[0], 0.1);
  431. UNIT_ASSERT_EQUAL(values[1], 0.2);
  432. UNIT_ASSERT_EQUAL(values[2], 0.3);
  433. }
  434. );
  435. }
  436. Y_UNIT_TEST(PyInvertDict) {
  437. TPythonTestEngine engine;
  438. engine.ToPythonAndBack<NUdf::TDict<i32, double>, NUdf::TDict<double, i32>>(
  439. [](const TType* type, const NUdf::IValueBuilder& vb) {
  440. return vb.NewDict(type, NUdf::TDictFlags::Hashed)->
  441. Add(NUdf::TUnboxedValuePod((i32) 1), NUdf::TUnboxedValuePod((double) 0.1))
  442. .Add(NUdf::TUnboxedValuePod((i32) 2), NUdf::TUnboxedValuePod((double) 0.2))
  443. .Add(NUdf::TUnboxedValuePod((i32) 3), NUdf::TUnboxedValuePod((double) 0.3))
  444. .Build();
  445. },
  446. "def Test(value): return { v: k for k, v in value.items() }",
  447. [](const NUdf::TUnboxedValuePod& value) {
  448. UNIT_ASSERT(value.HasDictItems());
  449. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  450. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod((double) 0.1)));
  451. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod((double) 0.0)));
  452. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod((double) 0.4)));
  453. UNIT_ASSERT_EQUAL(value.Lookup(NUdf::TUnboxedValuePod((double) 0.2)).Get<i32>(), 2);
  454. std::map<double, i32> items;
  455. const auto it = value.GetDictIterator();
  456. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  457. items.emplace(key.Get<double>(), payload.Get<i32>());
  458. }
  459. UNIT_ASSERT_EQUAL(items.size(), 3);
  460. UNIT_ASSERT_EQUAL(items[0.1], 1);
  461. UNIT_ASSERT_EQUAL(items[0.2], 2);
  462. UNIT_ASSERT_EQUAL(items[0.3], 3);
  463. }
  464. );
  465. }
  466. Y_UNIT_TEST(FromPyOrderedDict) {
  467. TPythonTestEngine engine;
  468. engine.ToMiniKQL<NUdf::TDict<ui32, char*>>(
  469. "from collections import OrderedDict\n"
  470. "def Test(): return OrderedDict([(2, 'two'), (1, 'one'), (3, 'three')])\n",
  471. [](const NUdf::TUnboxedValuePod& value) {
  472. UNIT_ASSERT(value);
  473. UNIT_ASSERT(value.IsBoxed());
  474. UNIT_ASSERT(value.HasDictItems());
  475. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  476. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(ui32(1))));
  477. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(ui32(0))));
  478. const auto v = value.Lookup(NUdf::TUnboxedValuePod(ui32(1)));
  479. UNIT_ASSERT_EQUAL(v.AsStringRef(), "one");
  480. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod((ui32(4)))));
  481. #if PY_MAJOR_VERSION >= 3
  482. std::vector<std::pair<ui32, TString>> items;
  483. const auto it = value.GetDictIterator();
  484. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  485. items.emplace_back(key.Get<ui32>(), payload.AsStringRef());
  486. }
  487. UNIT_ASSERT_EQUAL(items.size(), 3);
  488. UNIT_ASSERT_EQUAL(items[0].first, 2);
  489. UNIT_ASSERT_EQUAL(items[1].first, 1);
  490. UNIT_ASSERT_EQUAL(items[2].first, 3);
  491. UNIT_ASSERT_EQUAL(items[0].second, "two");
  492. UNIT_ASSERT_EQUAL(items[1].second, "one");
  493. UNIT_ASSERT_EQUAL(items[2].second, "three");
  494. std::vector<ui32> keys;
  495. const auto kit = value.GetKeysIterator();
  496. for (NUdf::TUnboxedValue key; kit.Next(key);) {
  497. keys.emplace_back(key.Get<ui32>());
  498. }
  499. UNIT_ASSERT_EQUAL(keys.size(), 3);
  500. UNIT_ASSERT_EQUAL(keys[0], 2);
  501. UNIT_ASSERT_EQUAL(keys[1], 1);
  502. UNIT_ASSERT_EQUAL(keys[2], 3);
  503. std::vector<TString> values;
  504. const auto pit = value.GetPayloadsIterator();
  505. for (NUdf::TUnboxedValue payload; pit.Next(payload);) {
  506. values.emplace_back(payload.AsStringRef());
  507. }
  508. UNIT_ASSERT_EQUAL(values.size(), 3);
  509. UNIT_ASSERT_EQUAL(values[0], "two");
  510. UNIT_ASSERT_EQUAL(values[1], "one");
  511. UNIT_ASSERT_EQUAL(values[2], "three");
  512. #endif
  513. });
  514. }
  515. Y_UNIT_TEST(ToPyAndBackSetAsIs) {
  516. TPythonTestEngine engine;
  517. engine.ToPythonAndBack<NUdf::TDict<float, void>>(
  518. [](const TType* type, const NUdf::IValueBuilder& vb) {
  519. return vb.NewDict(type, NUdf::TDictFlags::Sorted)->
  520. Add(NUdf::TUnboxedValuePod(0.1f), NUdf::TUnboxedValuePod::Void())
  521. .Add(NUdf::TUnboxedValuePod(0.2f), NUdf::TUnboxedValuePod::Void())
  522. .Add(NUdf::TUnboxedValuePod(0.3f), NUdf::TUnboxedValuePod::Void())
  523. .Build();
  524. },
  525. "def Test(value): return value",
  526. [](const NUdf::TUnboxedValuePod& value) {
  527. UNIT_ASSERT(value.HasDictItems());
  528. UNIT_ASSERT_EQUAL(value.GetDictLength(), 3);
  529. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(0.0f)));
  530. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(0.3f)));
  531. UNIT_ASSERT(value.Lookup(NUdf::TUnboxedValuePod(0.2f)));
  532. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(0.4f)));
  533. std::vector<float> keys;
  534. const auto kit = value.GetKeysIterator();
  535. for (NUdf::TUnboxedValue key; kit.Next(key);) {
  536. keys.emplace_back(key.Get<float>());
  537. }
  538. UNIT_ASSERT_EQUAL(keys.size(), 3);
  539. UNIT_ASSERT_EQUAL(keys[0], 0.1f);
  540. UNIT_ASSERT_EQUAL(keys[1], 0.2f);
  541. UNIT_ASSERT_EQUAL(keys[2], 0.3f);
  542. }
  543. );
  544. }
  545. Y_UNIT_TEST(ToPyAsThinList_FromPyAsDict) {
  546. TPythonTestEngine engine;
  547. engine.ToPythonAndBack<NUdf::TListType<float>, NUdf::TDict<i8, float>>(
  548. [](const TType*, const NUdf::IValueBuilder& vb) {
  549. NUdf::TUnboxedValue *items = nullptr;
  550. const auto a = vb.NewArray(9U, items);
  551. const float f[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f };
  552. std::transform(f, f + 9U, items, [](float v){ return NUdf::TUnboxedValuePod(v); });
  553. return a;
  554. },
  555. "def Test(value): return value",
  556. [](const NUdf::TUnboxedValuePod& value) {
  557. UNIT_ASSERT(value.HasDictItems());
  558. UNIT_ASSERT_EQUAL(value.GetDictLength(), 9U);
  559. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(i8(0))));
  560. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(i8(10))));
  561. UNIT_ASSERT_EQUAL(value.Lookup(NUdf::TUnboxedValuePod(i8(5))).Get<float>(), 0.6f);
  562. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(i8(13))));
  563. std::vector<std::pair<i8, float>> items;
  564. const auto it = value.GetDictIterator();
  565. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  566. items.emplace_back(key.Get<i8>(), payload.Get<float>());
  567. }
  568. UNIT_ASSERT_EQUAL(items.size(), 9U);
  569. UNIT_ASSERT_EQUAL(items.front().first, 0);
  570. UNIT_ASSERT_EQUAL(items.back().first, 8);
  571. UNIT_ASSERT_EQUAL(items.front().second, 0.1f);
  572. UNIT_ASSERT_EQUAL(items.back().second, 0.9f);
  573. std::vector<i8> keys;
  574. const auto kit = value.GetKeysIterator();
  575. for (NUdf::TUnboxedValue key; kit.Next(key);) {
  576. keys.emplace_back(key.Get<i8>());
  577. }
  578. UNIT_ASSERT_EQUAL(keys.size(), 9U);
  579. UNIT_ASSERT_EQUAL(keys.front(), 0);
  580. UNIT_ASSERT_EQUAL(keys.back(), 8);
  581. std::vector<float> values;
  582. const auto pit = value.GetPayloadsIterator();
  583. for (NUdf::TUnboxedValue payload; pit.Next(payload);) {
  584. values.emplace_back(payload.Get<float>());
  585. }
  586. UNIT_ASSERT_EQUAL(values.size(), 9U);
  587. UNIT_ASSERT_EQUAL(values.front(), 0.1f);
  588. UNIT_ASSERT_EQUAL(values.back(), 0.9f);
  589. }
  590. );
  591. }
  592. Y_UNIT_TEST(ToPyAsLazyList_FromPyAsDict) {
  593. TPythonTestEngine engine;
  594. engine.ToPythonAndBack<NUdf::TListType<i32>, NUdf::TDict<ui8, i32>>(
  595. [](const TType*, const NUdf::IValueBuilder&) {
  596. return NUdf::TUnboxedValuePod(new NUdf::TLazyList<false>(1, 10));
  597. },
  598. "def Test(value): return value",
  599. [](const NUdf::TUnboxedValuePod& value) {
  600. UNIT_ASSERT(value.HasDictItems());
  601. UNIT_ASSERT_EQUAL(value.GetDictLength(), 9U);
  602. UNIT_ASSERT(value.Contains(NUdf::TUnboxedValuePod(ui8(0))));
  603. UNIT_ASSERT(!value.Contains(NUdf::TUnboxedValuePod(ui8(10))));
  604. UNIT_ASSERT_EQUAL(value.Lookup(NUdf::TUnboxedValuePod(ui8(5))).Get<i32>(), 6);
  605. UNIT_ASSERT(!value.Lookup(NUdf::TUnboxedValuePod(ui8(13))));
  606. std::vector<std::pair<ui8, i32>> items;
  607. const auto it = value.GetDictIterator();
  608. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  609. items.emplace_back(key.Get<ui8>(), payload.Get<i32>());
  610. }
  611. UNIT_ASSERT_EQUAL(items.size(), 9U);
  612. UNIT_ASSERT_EQUAL(items.front().first, 0);
  613. UNIT_ASSERT_EQUAL(items.back().first, 8);
  614. UNIT_ASSERT_EQUAL(items.front().second, 1);
  615. UNIT_ASSERT_EQUAL(items.back().second, 9);
  616. std::vector<ui8> keys;
  617. const auto kit = value.GetKeysIterator();
  618. for (NUdf::TUnboxedValue key; kit.Next(key);) {
  619. keys.emplace_back(key.Get<ui8>());
  620. }
  621. UNIT_ASSERT_EQUAL(keys.size(), 9U);
  622. UNIT_ASSERT_EQUAL(keys.front(), 0);
  623. UNIT_ASSERT_EQUAL(keys.back(), 8);
  624. std::vector<i32> values;
  625. const auto pit = value.GetPayloadsIterator();
  626. for (NUdf::TUnboxedValue payload; pit.Next(payload);) {
  627. values.emplace_back(payload.Get<i32>());
  628. }
  629. UNIT_ASSERT_EQUAL(values.size(), 9U);
  630. UNIT_ASSERT_EQUAL(values.front(), 1);
  631. UNIT_ASSERT_EQUAL(values.back(), 9);
  632. }
  633. );
  634. }
  635. }