maxframe 2.0.0b2__cp310-cp310-win_amd64.whl → 2.2.0__cp310-cp310-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of maxframe might be problematic. Click here for more details.

Files changed (391) hide show
  1. maxframe/__init__.py +1 -0
  2. maxframe/_utils.cp310-win_amd64.pyd +0 -0
  3. maxframe/_utils.pyx +14 -1
  4. maxframe/codegen/core.py +6 -6
  5. maxframe/codegen/spe/core.py +1 -1
  6. maxframe/codegen/spe/dataframe/__init__.py +1 -0
  7. maxframe/codegen/spe/dataframe/accessors/base.py +18 -0
  8. maxframe/codegen/spe/dataframe/accessors/dict_.py +25 -130
  9. maxframe/codegen/spe/dataframe/accessors/list_.py +12 -48
  10. maxframe/codegen/spe/dataframe/accessors/struct_.py +28 -0
  11. maxframe/codegen/spe/dataframe/arithmetic.py +7 -2
  12. maxframe/codegen/spe/dataframe/groupby.py +88 -0
  13. maxframe/codegen/spe/dataframe/indexing.py +99 -4
  14. maxframe/codegen/spe/dataframe/merge.py +34 -1
  15. maxframe/codegen/spe/dataframe/misc.py +9 -33
  16. maxframe/codegen/spe/dataframe/reduction.py +14 -9
  17. maxframe/codegen/spe/dataframe/reshape.py +46 -0
  18. maxframe/codegen/spe/dataframe/sort.py +30 -17
  19. maxframe/codegen/spe/dataframe/tests/accessors/test_dict.py +9 -15
  20. maxframe/codegen/spe/dataframe/tests/accessors/test_list.py +4 -7
  21. maxframe/codegen/spe/dataframe/tests/accessors/test_struct.py +75 -0
  22. maxframe/codegen/spe/dataframe/tests/indexing/test_iloc.py +20 -1
  23. maxframe/codegen/spe/dataframe/tests/indexing/test_loc.py +35 -0
  24. maxframe/codegen/spe/dataframe/tests/misc/test_misc.py +0 -32
  25. maxframe/codegen/spe/dataframe/tests/test_groupby.py +81 -18
  26. maxframe/codegen/spe/dataframe/tests/test_merge.py +27 -1
  27. maxframe/codegen/spe/dataframe/tests/test_reshape.py +79 -0
  28. maxframe/codegen/spe/dataframe/tests/test_sort.py +20 -0
  29. maxframe/codegen/spe/learn/contrib/tests/test_xgboost.py +2 -1
  30. maxframe/codegen/spe/learn/metrics/__init__.py +1 -1
  31. maxframe/codegen/spe/learn/metrics/_ranking.py +76 -0
  32. maxframe/codegen/spe/learn/metrics/pairwise.py +51 -0
  33. maxframe/codegen/spe/learn/metrics/tests/test_pairwise.py +36 -0
  34. maxframe/codegen/spe/learn/metrics/tests/test_ranking.py +59 -0
  35. maxframe/codegen/spe/tensor/__init__.py +3 -0
  36. maxframe/codegen/spe/tensor/fft.py +74 -0
  37. maxframe/codegen/spe/tensor/linalg.py +29 -2
  38. maxframe/codegen/spe/tensor/misc.py +79 -25
  39. maxframe/codegen/spe/tensor/spatial.py +45 -0
  40. maxframe/codegen/spe/tensor/statistics.py +44 -0
  41. maxframe/codegen/spe/tensor/tests/test_fft.py +64 -0
  42. maxframe/codegen/spe/tensor/tests/test_linalg.py +15 -1
  43. maxframe/codegen/spe/tensor/tests/test_misc.py +52 -2
  44. maxframe/codegen/spe/tensor/tests/test_spatial.py +33 -0
  45. maxframe/codegen/spe/tensor/tests/test_statistics.py +15 -1
  46. maxframe/codegen/spe/tests/test_spe_codegen.py +6 -12
  47. maxframe/codegen/spe/utils.py +2 -0
  48. maxframe/config/config.py +70 -9
  49. maxframe/config/tests/test_validators.py +13 -1
  50. maxframe/config/validators.py +49 -0
  51. maxframe/conftest.py +44 -17
  52. maxframe/core/accessor.py +2 -2
  53. maxframe/core/entity/core.py +5 -0
  54. maxframe/core/entity/tileables.py +1 -1
  55. maxframe/core/graph/core.cp310-win_amd64.pyd +0 -0
  56. maxframe/core/graph/entity.py +1 -2
  57. maxframe/core/operator/base.py +9 -2
  58. maxframe/core/operator/core.py +10 -2
  59. maxframe/core/operator/utils.py +13 -0
  60. maxframe/dataframe/__init__.py +10 -3
  61. maxframe/dataframe/accessors/__init__.py +1 -1
  62. maxframe/dataframe/accessors/compat.py +45 -0
  63. maxframe/dataframe/accessors/datetime_/__init__.py +4 -1
  64. maxframe/dataframe/accessors/dict_/contains.py +7 -16
  65. maxframe/dataframe/accessors/dict_/core.py +48 -0
  66. maxframe/dataframe/accessors/dict_/getitem.py +17 -21
  67. maxframe/dataframe/accessors/dict_/length.py +7 -16
  68. maxframe/dataframe/accessors/dict_/remove.py +6 -18
  69. maxframe/dataframe/accessors/dict_/setitem.py +8 -18
  70. maxframe/dataframe/accessors/dict_/tests/test_dict_accessor.py +62 -22
  71. maxframe/dataframe/accessors/list_/__init__.py +2 -2
  72. maxframe/dataframe/accessors/list_/core.py +48 -0
  73. maxframe/dataframe/accessors/list_/getitem.py +12 -19
  74. maxframe/dataframe/accessors/list_/length.py +7 -16
  75. maxframe/dataframe/accessors/list_/tests/test_list_accessor.py +11 -9
  76. maxframe/dataframe/accessors/string_/__init__.py +4 -1
  77. maxframe/dataframe/accessors/struct_/__init__.py +37 -0
  78. maxframe/dataframe/accessors/struct_/accessor.py +39 -0
  79. maxframe/dataframe/accessors/struct_/core.py +43 -0
  80. maxframe/dataframe/accessors/struct_/dtypes.py +53 -0
  81. maxframe/dataframe/accessors/struct_/field.py +123 -0
  82. maxframe/dataframe/accessors/struct_/tests/__init__.py +13 -0
  83. maxframe/dataframe/accessors/struct_/tests/test_struct_accessor.py +91 -0
  84. maxframe/dataframe/arithmetic/__init__.py +14 -4
  85. maxframe/dataframe/arithmetic/between.py +106 -0
  86. maxframe/dataframe/arithmetic/dot.py +237 -0
  87. maxframe/dataframe/arithmetic/{around.py → round.py} +11 -7
  88. maxframe/dataframe/core.py +63 -118
  89. maxframe/dataframe/datasource/__init__.py +18 -0
  90. maxframe/dataframe/datasource/from_dict.py +124 -0
  91. maxframe/dataframe/datasource/from_index.py +1 -1
  92. maxframe/dataframe/datasource/from_records.py +77 -0
  93. maxframe/dataframe/datasource/from_tensor.py +109 -41
  94. maxframe/dataframe/datasource/read_csv.py +2 -3
  95. maxframe/dataframe/datasource/tests/test_datasource.py +37 -0
  96. maxframe/dataframe/datastore/__init__.py +5 -1
  97. maxframe/dataframe/datastore/to_csv.py +29 -41
  98. maxframe/dataframe/datastore/to_odps.py +30 -4
  99. maxframe/dataframe/extensions/__init__.py +20 -4
  100. maxframe/dataframe/extensions/apply_chunk.py +32 -6
  101. maxframe/dataframe/extensions/cartesian_chunk.py +153 -0
  102. maxframe/dataframe/extensions/collect_kv.py +126 -0
  103. maxframe/dataframe/extensions/extract_kv.py +177 -0
  104. maxframe/dataframe/extensions/map_reduce.py +263 -0
  105. maxframe/dataframe/extensions/rebalance.py +62 -0
  106. maxframe/dataframe/extensions/tests/test_apply_chunk.py +9 -2
  107. maxframe/dataframe/extensions/tests/test_extensions.py +54 -0
  108. maxframe/dataframe/extensions/tests/test_map_reduce.py +135 -0
  109. maxframe/dataframe/groupby/__init__.py +12 -1
  110. maxframe/dataframe/groupby/aggregation.py +78 -45
  111. maxframe/dataframe/groupby/apply.py +1 -1
  112. maxframe/dataframe/groupby/apply_chunk.py +18 -2
  113. maxframe/dataframe/groupby/core.py +96 -12
  114. maxframe/dataframe/groupby/cum.py +4 -25
  115. maxframe/dataframe/groupby/expanding.py +264 -0
  116. maxframe/dataframe/groupby/fill.py +1 -1
  117. maxframe/dataframe/groupby/getitem.py +12 -5
  118. maxframe/dataframe/groupby/head.py +11 -1
  119. maxframe/dataframe/groupby/rank.py +136 -0
  120. maxframe/dataframe/groupby/rolling.py +206 -0
  121. maxframe/dataframe/groupby/shift.py +114 -0
  122. maxframe/dataframe/groupby/tests/test_groupby.py +0 -5
  123. maxframe/dataframe/indexing/__init__.py +20 -1
  124. maxframe/dataframe/indexing/droplevel.py +195 -0
  125. maxframe/dataframe/indexing/filter.py +169 -0
  126. maxframe/dataframe/indexing/get_level_values.py +76 -0
  127. maxframe/dataframe/indexing/iat.py +45 -0
  128. maxframe/dataframe/indexing/iloc.py +152 -12
  129. maxframe/dataframe/indexing/insert.py +1 -1
  130. maxframe/dataframe/indexing/loc.py +287 -7
  131. maxframe/dataframe/indexing/reindex.py +14 -5
  132. maxframe/dataframe/indexing/rename.py +6 -0
  133. maxframe/dataframe/indexing/rename_axis.py +2 -2
  134. maxframe/dataframe/indexing/reorder_levels.py +143 -0
  135. maxframe/dataframe/indexing/reset_index.py +33 -6
  136. maxframe/dataframe/indexing/sample.py +8 -0
  137. maxframe/dataframe/indexing/setitem.py +3 -3
  138. maxframe/dataframe/indexing/swaplevel.py +185 -0
  139. maxframe/dataframe/indexing/take.py +99 -0
  140. maxframe/dataframe/indexing/truncate.py +140 -0
  141. maxframe/dataframe/indexing/where.py +0 -11
  142. maxframe/dataframe/indexing/xs.py +148 -0
  143. maxframe/dataframe/merge/__init__.py +12 -1
  144. maxframe/dataframe/merge/append.py +97 -98
  145. maxframe/dataframe/merge/combine_first.py +120 -0
  146. maxframe/dataframe/merge/compare.py +387 -0
  147. maxframe/dataframe/merge/concat.py +183 -0
  148. maxframe/dataframe/merge/update.py +271 -0
  149. maxframe/dataframe/misc/__init__.py +16 -10
  150. maxframe/dataframe/misc/_duplicate.py +10 -4
  151. maxframe/dataframe/misc/apply.py +1 -1
  152. maxframe/dataframe/misc/check_unique.py +51 -0
  153. maxframe/dataframe/misc/clip.py +145 -0
  154. maxframe/dataframe/misc/describe.py +175 -9
  155. maxframe/dataframe/misc/drop_duplicates.py +2 -2
  156. maxframe/dataframe/misc/duplicated.py +2 -2
  157. maxframe/dataframe/misc/get_dummies.py +5 -1
  158. maxframe/dataframe/misc/isin.py +2 -2
  159. maxframe/dataframe/misc/map.py +94 -0
  160. maxframe/dataframe/misc/tests/test_misc.py +13 -2
  161. maxframe/dataframe/misc/to_numeric.py +3 -0
  162. maxframe/dataframe/misc/transform.py +12 -5
  163. maxframe/dataframe/misc/transpose.py +13 -1
  164. maxframe/dataframe/misc/valid_index.py +115 -0
  165. maxframe/dataframe/misc/value_counts.py +38 -4
  166. maxframe/dataframe/missing/checkna.py +13 -6
  167. maxframe/dataframe/missing/dropna.py +5 -0
  168. maxframe/dataframe/missing/fillna.py +1 -1
  169. maxframe/dataframe/missing/replace.py +7 -4
  170. maxframe/dataframe/reduction/__init__.py +29 -15
  171. maxframe/dataframe/reduction/aggregation.py +38 -9
  172. maxframe/dataframe/reduction/all.py +2 -2
  173. maxframe/dataframe/reduction/any.py +2 -2
  174. maxframe/dataframe/reduction/argmax.py +100 -0
  175. maxframe/dataframe/reduction/argmin.py +100 -0
  176. maxframe/dataframe/reduction/core.py +65 -18
  177. maxframe/dataframe/reduction/count.py +13 -9
  178. maxframe/dataframe/reduction/cov.py +166 -0
  179. maxframe/dataframe/reduction/cummax.py +2 -2
  180. maxframe/dataframe/reduction/cummin.py +2 -2
  181. maxframe/dataframe/reduction/cumprod.py +2 -2
  182. maxframe/dataframe/reduction/cumsum.py +2 -2
  183. maxframe/dataframe/reduction/custom_reduction.py +2 -2
  184. maxframe/dataframe/reduction/idxmax.py +185 -0
  185. maxframe/dataframe/reduction/idxmin.py +185 -0
  186. maxframe/dataframe/reduction/kurtosis.py +37 -30
  187. maxframe/dataframe/reduction/max.py +2 -2
  188. maxframe/dataframe/reduction/mean.py +9 -7
  189. maxframe/dataframe/reduction/median.py +2 -2
  190. maxframe/dataframe/reduction/min.py +2 -2
  191. maxframe/dataframe/reduction/nunique.py +9 -8
  192. maxframe/dataframe/reduction/prod.py +18 -13
  193. maxframe/dataframe/reduction/reduction_size.py +2 -2
  194. maxframe/dataframe/reduction/sem.py +13 -9
  195. maxframe/dataframe/reduction/skew.py +31 -27
  196. maxframe/dataframe/reduction/str_concat.py +10 -7
  197. maxframe/dataframe/reduction/sum.py +18 -14
  198. maxframe/dataframe/reduction/unique.py +20 -3
  199. maxframe/dataframe/reduction/var.py +16 -12
  200. maxframe/dataframe/reshape/__init__.py +38 -0
  201. maxframe/dataframe/{misc → reshape}/pivot.py +1 -0
  202. maxframe/dataframe/{misc → reshape}/pivot_table.py +1 -0
  203. maxframe/dataframe/reshape/unstack.py +114 -0
  204. maxframe/dataframe/sort/__init__.py +8 -0
  205. maxframe/dataframe/sort/argsort.py +62 -0
  206. maxframe/dataframe/sort/core.py +1 -0
  207. maxframe/dataframe/sort/nlargest.py +238 -0
  208. maxframe/dataframe/sort/nsmallest.py +228 -0
  209. maxframe/dataframe/statistics/__init__.py +3 -3
  210. maxframe/dataframe/statistics/corr.py +1 -0
  211. maxframe/dataframe/statistics/quantile.py +2 -2
  212. maxframe/dataframe/tests/test_typing.py +104 -0
  213. maxframe/dataframe/tests/test_utils.py +66 -2
  214. maxframe/dataframe/typing_.py +185 -0
  215. maxframe/dataframe/utils.py +95 -26
  216. maxframe/dataframe/window/aggregation.py +8 -4
  217. maxframe/dataframe/window/core.py +14 -1
  218. maxframe/dataframe/window/ewm.py +1 -3
  219. maxframe/dataframe/window/expanding.py +37 -35
  220. maxframe/dataframe/window/rolling.py +49 -39
  221. maxframe/dataframe/window/tests/test_expanding.py +1 -7
  222. maxframe/dataframe/window/tests/test_rolling.py +1 -1
  223. maxframe/env.py +7 -4
  224. maxframe/errors.py +2 -2
  225. maxframe/io/odpsio/schema.py +9 -3
  226. maxframe/io/odpsio/tableio.py +7 -2
  227. maxframe/io/odpsio/tests/test_schema.py +198 -83
  228. maxframe/learn/__init__.py +10 -2
  229. maxframe/learn/cluster/__init__.py +15 -0
  230. maxframe/learn/cluster/_kmeans.py +782 -0
  231. maxframe/learn/contrib/llm/core.py +2 -0
  232. maxframe/learn/contrib/xgboost/core.py +86 -1
  233. maxframe/learn/contrib/xgboost/train.py +5 -2
  234. maxframe/learn/core.py +66 -0
  235. maxframe/learn/linear_model/_base.py +58 -1
  236. maxframe/learn/linear_model/_lin_reg.py +1 -1
  237. maxframe/learn/metrics/__init__.py +6 -0
  238. maxframe/learn/metrics/_classification.py +145 -0
  239. maxframe/learn/metrics/_ranking.py +477 -0
  240. maxframe/learn/metrics/_scorer.py +60 -0
  241. maxframe/learn/metrics/pairwise/__init__.py +21 -0
  242. maxframe/learn/metrics/pairwise/core.py +77 -0
  243. maxframe/learn/metrics/pairwise/cosine.py +115 -0
  244. maxframe/learn/metrics/pairwise/euclidean.py +176 -0
  245. maxframe/learn/metrics/pairwise/haversine.py +96 -0
  246. maxframe/learn/metrics/pairwise/manhattan.py +80 -0
  247. maxframe/learn/metrics/pairwise/pairwise.py +127 -0
  248. maxframe/learn/metrics/pairwise/pairwise_distances_topk.py +121 -0
  249. maxframe/learn/metrics/pairwise/rbf_kernel.py +51 -0
  250. maxframe/learn/metrics/tests/__init__.py +13 -0
  251. maxframe/learn/metrics/tests/test_scorer.py +26 -0
  252. maxframe/learn/utils/__init__.py +1 -1
  253. maxframe/learn/utils/checks.py +1 -2
  254. maxframe/learn/utils/core.py +59 -0
  255. maxframe/learn/utils/extmath.py +37 -0
  256. maxframe/learn/utils/odpsio.py +193 -0
  257. maxframe/learn/utils/validation.py +2 -2
  258. maxframe/lib/compat.py +40 -0
  259. maxframe/lib/dtypes_extension/__init__.py +16 -1
  260. maxframe/lib/dtypes_extension/_fake_arrow_dtype.py +604 -0
  261. maxframe/lib/dtypes_extension/blob.py +304 -0
  262. maxframe/lib/dtypes_extension/dtypes.py +40 -0
  263. maxframe/lib/dtypes_extension/tests/test_blob.py +88 -0
  264. maxframe/lib/dtypes_extension/tests/test_dtypes.py +16 -1
  265. maxframe/lib/dtypes_extension/tests/test_fake_arrow_dtype.py +75 -0
  266. maxframe/lib/filesystem/_oss_lib/common.py +122 -50
  267. maxframe/lib/filesystem/_oss_lib/glob.py +1 -1
  268. maxframe/lib/filesystem/_oss_lib/handle.py +21 -25
  269. maxframe/lib/filesystem/base.py +1 -1
  270. maxframe/lib/filesystem/core.py +1 -1
  271. maxframe/lib/filesystem/oss.py +115 -46
  272. maxframe/lib/filesystem/tests/test_oss.py +74 -36
  273. maxframe/lib/mmh3.cp310-win_amd64.pyd +0 -0
  274. maxframe/lib/wrapped_pickle.py +10 -0
  275. maxframe/opcodes.py +33 -15
  276. maxframe/protocol.py +12 -0
  277. maxframe/serialization/__init__.py +11 -2
  278. maxframe/serialization/arrow.py +38 -13
  279. maxframe/serialization/blob.py +32 -0
  280. maxframe/serialization/core.cp310-win_amd64.pyd +0 -0
  281. maxframe/serialization/core.pyx +39 -1
  282. maxframe/serialization/exception.py +2 -4
  283. maxframe/serialization/numpy.py +11 -0
  284. maxframe/serialization/pandas.py +46 -9
  285. maxframe/serialization/serializables/core.py +2 -2
  286. maxframe/serialization/tests/test_serial.py +29 -2
  287. maxframe/tensor/__init__.py +38 -8
  288. maxframe/tensor/arithmetic/__init__.py +19 -10
  289. maxframe/tensor/arithmetic/iscomplexobj.py +53 -0
  290. maxframe/tensor/arithmetic/tests/test_arithmetic.py +6 -0
  291. maxframe/tensor/core.py +3 -2
  292. maxframe/tensor/datasource/tests/test_datasource.py +2 -1
  293. maxframe/tensor/extensions/__init__.py +2 -0
  294. maxframe/tensor/extensions/apply_chunk.py +3 -3
  295. maxframe/tensor/extensions/rebalance.py +65 -0
  296. maxframe/tensor/fft/__init__.py +32 -0
  297. maxframe/tensor/fft/core.py +168 -0
  298. maxframe/tensor/fft/fft.py +112 -0
  299. maxframe/tensor/fft/fft2.py +118 -0
  300. maxframe/tensor/fft/fftfreq.py +80 -0
  301. maxframe/tensor/fft/fftn.py +123 -0
  302. maxframe/tensor/fft/fftshift.py +79 -0
  303. maxframe/tensor/fft/hfft.py +112 -0
  304. maxframe/tensor/fft/ifft.py +114 -0
  305. maxframe/tensor/fft/ifft2.py +115 -0
  306. maxframe/tensor/fft/ifftn.py +123 -0
  307. maxframe/tensor/fft/ifftshift.py +73 -0
  308. maxframe/tensor/fft/ihfft.py +93 -0
  309. maxframe/tensor/fft/irfft.py +118 -0
  310. maxframe/tensor/fft/irfft2.py +62 -0
  311. maxframe/tensor/fft/irfftn.py +114 -0
  312. maxframe/tensor/fft/rfft.py +116 -0
  313. maxframe/tensor/fft/rfft2.py +63 -0
  314. maxframe/tensor/fft/rfftfreq.py +87 -0
  315. maxframe/tensor/fft/rfftn.py +113 -0
  316. maxframe/tensor/indexing/fill_diagonal.py +1 -7
  317. maxframe/tensor/linalg/__init__.py +7 -0
  318. maxframe/tensor/linalg/_einsumfunc.py +1025 -0
  319. maxframe/tensor/linalg/cholesky.py +117 -0
  320. maxframe/tensor/linalg/einsum.py +339 -0
  321. maxframe/tensor/linalg/lstsq.py +100 -0
  322. maxframe/tensor/linalg/matrix_norm.py +75 -0
  323. maxframe/tensor/linalg/norm.py +249 -0
  324. maxframe/tensor/linalg/solve.py +72 -0
  325. maxframe/tensor/linalg/solve_triangular.py +2 -2
  326. maxframe/tensor/linalg/vector_norm.py +113 -0
  327. maxframe/tensor/misc/__init__.py +24 -1
  328. maxframe/tensor/misc/argwhere.py +72 -0
  329. maxframe/tensor/misc/array_split.py +46 -0
  330. maxframe/tensor/misc/broadcast_arrays.py +57 -0
  331. maxframe/tensor/misc/copyto.py +130 -0
  332. maxframe/tensor/misc/delete.py +104 -0
  333. maxframe/tensor/misc/dsplit.py +68 -0
  334. maxframe/tensor/misc/ediff1d.py +74 -0
  335. maxframe/tensor/misc/expand_dims.py +85 -0
  336. maxframe/tensor/misc/flip.py +90 -0
  337. maxframe/tensor/misc/fliplr.py +64 -0
  338. maxframe/tensor/misc/flipud.py +68 -0
  339. maxframe/tensor/misc/hsplit.py +85 -0
  340. maxframe/tensor/misc/insert.py +139 -0
  341. maxframe/tensor/misc/moveaxis.py +83 -0
  342. maxframe/tensor/misc/result_type.py +88 -0
  343. maxframe/tensor/misc/roll.py +124 -0
  344. maxframe/tensor/misc/rollaxis.py +77 -0
  345. maxframe/tensor/misc/shape.py +89 -0
  346. maxframe/tensor/misc/split.py +190 -0
  347. maxframe/tensor/misc/tile.py +109 -0
  348. maxframe/tensor/misc/vsplit.py +74 -0
  349. maxframe/tensor/reduction/array_equal.py +2 -1
  350. maxframe/tensor/sort/__init__.py +2 -0
  351. maxframe/tensor/sort/argpartition.py +98 -0
  352. maxframe/tensor/sort/partition.py +228 -0
  353. maxframe/tensor/spatial/__init__.py +15 -0
  354. maxframe/tensor/spatial/distance/__init__.py +17 -0
  355. maxframe/tensor/spatial/distance/cdist.py +421 -0
  356. maxframe/tensor/spatial/distance/pdist.py +398 -0
  357. maxframe/tensor/spatial/distance/squareform.py +153 -0
  358. maxframe/tensor/special/__init__.py +159 -21
  359. maxframe/tensor/special/airy.py +55 -0
  360. maxframe/tensor/special/bessel.py +199 -0
  361. maxframe/tensor/special/core.py +65 -4
  362. maxframe/tensor/special/ellip_func_integrals.py +155 -0
  363. maxframe/tensor/special/ellip_harm.py +55 -0
  364. maxframe/tensor/special/err_fresnel.py +223 -0
  365. maxframe/tensor/special/gamma_funcs.py +303 -0
  366. maxframe/tensor/special/hypergeometric_funcs.py +69 -0
  367. maxframe/tensor/special/info_theory.py +189 -0
  368. maxframe/tensor/special/misc.py +21 -0
  369. maxframe/tensor/statistics/__init__.py +6 -0
  370. maxframe/tensor/statistics/corrcoef.py +77 -0
  371. maxframe/tensor/statistics/cov.py +222 -0
  372. maxframe/tensor/statistics/digitize.py +126 -0
  373. maxframe/tensor/statistics/histogram.py +520 -0
  374. maxframe/tensor/statistics/median.py +85 -0
  375. maxframe/tensor/statistics/ptp.py +89 -0
  376. maxframe/tensor/utils.py +3 -3
  377. maxframe/tests/test_utils.py +43 -1
  378. maxframe/tests/utils.py +0 -2
  379. maxframe/typing_.py +2 -0
  380. maxframe/udf.py +27 -2
  381. maxframe/utils.py +193 -19
  382. {maxframe-2.0.0b2.dist-info → maxframe-2.2.0.dist-info}/METADATA +3 -2
  383. {maxframe-2.0.0b2.dist-info → maxframe-2.2.0.dist-info}/RECORD +391 -236
  384. maxframe_client/fetcher.py +35 -4
  385. maxframe_client/session/odps.py +7 -2
  386. maxframe_client/tests/test_fetcher.py +76 -3
  387. maxframe_client/tests/test_session.py +4 -1
  388. /maxframe/dataframe/{misc → reshape}/melt.py +0 -0
  389. /maxframe/dataframe/{misc → reshape}/stack.py +0 -0
  390. {maxframe-2.0.0b2.dist-info → maxframe-2.2.0.dist-info}/WHEEL +0 -0
  391. {maxframe-2.0.0b2.dist-info → maxframe-2.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,121 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import List
16
+
17
+ import numpy as np
18
+
19
+ from .... import opcodes
20
+ from ....config import options
21
+ from ....core import EntityData
22
+ from ....core.operator import OperatorStage
23
+ from ....serialization.serializables import (
24
+ AnyField,
25
+ BoolField,
26
+ DictField,
27
+ Int64Field,
28
+ KeyField,
29
+ )
30
+ from ....tensor.core import TensorOrder
31
+ from .core import PairwiseDistances
32
+
33
+
34
+ class PairwiseDistancesTopk(PairwiseDistances):
35
+ _op_type_ = opcodes.PAIRWISE_DISTANCES_TOPK
36
+
37
+ x = KeyField("x")
38
+ y = KeyField("y")
39
+ k = Int64Field("k", default=None)
40
+ metric = AnyField("metric", default=None)
41
+ metric_kwargs = DictField("metric_kwargs", default=None)
42
+ return_index = BoolField("return_index", default=None)
43
+ working_memory = AnyField("working_memory", default=None)
44
+
45
+ @property
46
+ def output_limit(self):
47
+ return 2 if self.return_index else 1
48
+
49
+ @classmethod
50
+ def _set_inputs(cls, op: "PairwiseDistancesTopk", inputs: List[EntityData]):
51
+ super()._set_inputs(op, inputs)
52
+ if op.stage != OperatorStage.agg:
53
+ op.x, op.y = inputs[:2]
54
+ else:
55
+ op.x = op.y = None
56
+
57
+ def __call__(self, X, Y):
58
+ from .pairwise import pairwise_distances
59
+
60
+ # leverage pairwise_distances for checks
61
+ d = pairwise_distances(X, Y, metric=self.metric, **self.metric_kwargs)
62
+
63
+ if self.k > Y.shape[0]:
64
+ self.k = Y.shape[0]
65
+
66
+ X, Y = d.op.inputs
67
+
68
+ shape_list = [X.shape[0]]
69
+ shape_list.append(min(Y.shape[0], self.k))
70
+ shape = tuple(shape_list)
71
+ kws = [
72
+ {
73
+ "shape": shape,
74
+ "order": TensorOrder.C_ORDER,
75
+ "dtype": np.dtype(np.float64),
76
+ "_type_": "distance",
77
+ },
78
+ ]
79
+ if self.return_index:
80
+ kws.append(
81
+ {
82
+ "shape": shape,
83
+ "order": TensorOrder.C_ORDER,
84
+ "dtype": np.dtype(np.int64),
85
+ "_type_": "index",
86
+ }
87
+ )
88
+ return self.new_tensors([X, Y], kws=kws)
89
+ else:
90
+ return self.new_tensors([X, Y], kws=kws)[0]
91
+
92
+
93
+ def pairwise_distances_topk(
94
+ X,
95
+ Y=None,
96
+ k=None,
97
+ metric="euclidean",
98
+ return_index=True,
99
+ axis=1,
100
+ working_memory=None,
101
+ **kwds
102
+ ):
103
+ if k is None: # pragma: no cover
104
+ raise ValueError("`k` has to be specified")
105
+
106
+ if Y is None:
107
+ Y = X
108
+ if axis == 0:
109
+ X, Y = Y, X
110
+ if working_memory is None:
111
+ working_memory = options.learn.working_memory
112
+ op = PairwiseDistancesTopk(
113
+ x=X,
114
+ y=Y,
115
+ k=k,
116
+ metric=metric,
117
+ metric_kwargs=kwds,
118
+ return_index=return_index,
119
+ working_memory=working_memory,
120
+ )
121
+ return op(X, Y)
@@ -0,0 +1,51 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from .... import tensor as mt
16
+ from .core import PairwiseDistances
17
+ from .euclidean import euclidean_distances
18
+
19
+
20
+ def rbf_kernel(X, Y=None, gamma=None):
21
+ """
22
+ Compute the rbf (gaussian) kernel between X and Y::
23
+
24
+ K(x, y) = exp(-gamma ||x-y||^2)
25
+
26
+ for each pair of rows x in X and y in Y.
27
+
28
+ Read more in the :ref:`User Guide <rbf_kernel>`.
29
+
30
+ Parameters
31
+ ----------
32
+ X : tensor of shape (n_samples_X, n_features)
33
+
34
+ Y : tensor of shape (n_samples_Y, n_features)
35
+
36
+ gamma : float, default None
37
+ If None, defaults to 1.0 / n_features
38
+
39
+ Returns
40
+ -------
41
+ kernel_matrix : tensor of shape (n_samples_X, n_samples_Y)
42
+ """
43
+
44
+ X, Y = PairwiseDistances.check_pairwise_arrays(X, Y)
45
+ if gamma is None:
46
+ gamma = 1.0 / X.shape[1]
47
+
48
+ K = euclidean_distances(X, Y, squared=True)
49
+ K *= -gamma
50
+ K = mt.exp(K)
51
+ return K
@@ -0,0 +1,13 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,26 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import pytest
16
+ from sklearn.metrics import r2_score
17
+
18
+ from .. import get_scorer
19
+
20
+
21
+ def test_get_scorer():
22
+ with pytest.raises(ValueError):
23
+ get_scorer("unknown")
24
+
25
+ assert get_scorer("r2") is not None
26
+ assert get_scorer(r2_score) is not None
@@ -16,4 +16,4 @@ from .core import convert_to_tensor_or_dataframe
16
16
  from .multiclass import check_classification_targets
17
17
  from .shuffle import shuffle
18
18
  from .sparsefuncs import count_nonzero
19
- from .validation import check_consistent_length
19
+ from .validation import check_array, check_consistent_length
@@ -20,7 +20,7 @@ from ... import opcodes
20
20
  from ... import tensor as mt
21
21
  from ...config import options
22
22
  from ...core import ENTITY_TYPE, EntityData, OutputType, get_output_types
23
- from ...core.operator import Operator, OperatorStage
23
+ from ...core.operator import Operator
24
24
  from ...serialization.serializables import (
25
25
  BoolField,
26
26
  DataTypeField,
@@ -56,7 +56,6 @@ class CheckBase(Operator, LearnOperatorMixin):
56
56
  # output input if value not specified
57
57
  self.value = value = value if value is not None else x
58
58
  self.output_types = get_output_types(value)
59
- self.stage = OperatorStage.agg
60
59
  return self.new_tileable([x, value], kws=[value.params])
61
60
 
62
61
 
@@ -14,9 +14,19 @@
14
14
 
15
15
  import math
16
16
  import numbers
17
+ import warnings
17
18
 
19
+ import numpy as np
18
20
  import pandas as pd
19
21
 
22
+ from ...utils import parse_readable_size
23
+
24
+ try:
25
+ from sklearn import get_config as sklearn_get_config
26
+ except ImportError:
27
+ sklearn_get_config = None
28
+
29
+ from ...config import options
20
30
  from ...dataframe import DataFrame, Series
21
31
  from ...dataframe.core import DATAFRAME_TYPE, SERIES_TYPE
22
32
  from ...tensor import tensor as astensor
@@ -60,3 +70,52 @@ def is_scalar_nan(x):
60
70
  False
61
71
  """
62
72
  return isinstance(x, numbers.Real) and math.isnan(x)
73
+
74
+
75
+ def get_chunk_n_rows(row_bytes, max_n_rows=None, working_memory=None):
76
+ """Calculates how many rows can be processed within working_memory
77
+
78
+ Parameters
79
+ ----------
80
+ row_bytes : int
81
+ The expected number of bytes of memory that will be consumed
82
+ during the processing of each row.
83
+ max_n_rows : int, optional
84
+ The maximum return value.
85
+ working_memory : int or float, optional
86
+ The number of rows to fit inside this number of MiB will be returned.
87
+ When None (default), the value of
88
+ ``sklearn.get_config()['working_memory']`` is used.
89
+
90
+ Returns
91
+ -------
92
+ int or the value of n_samples
93
+
94
+ Warns
95
+ -----
96
+ Issues a UserWarning if ``row_bytes`` exceeds ``working_memory`` MiB.
97
+ """
98
+
99
+ if working_memory is None: # pragma: no cover
100
+ working_memory = options.learn.working_memory
101
+ if working_memory is None and sklearn_get_config is not None:
102
+ working_memory = sklearn_get_config()["working_memory"]
103
+ elif working_memory is None:
104
+ working_memory = 1024
105
+
106
+ if isinstance(working_memory, int):
107
+ working_memory *= 2**20
108
+ else:
109
+ working_memory = parse_readable_size(working_memory)[0]
110
+
111
+ chunk_n_rows = int(working_memory // row_bytes)
112
+ if max_n_rows is not None:
113
+ chunk_n_rows = min(chunk_n_rows, max_n_rows)
114
+ if chunk_n_rows < 1: # pragma: no cover
115
+ warnings.warn(
116
+ "Could not adhere to working_memory config. "
117
+ "Currently %.0fMiB, %.0fMiB required."
118
+ % (working_memory, np.ceil(row_bytes * 2**-20))
119
+ )
120
+ chunk_n_rows = 1
121
+ return chunk_n_rows
@@ -49,6 +49,19 @@ def _safe_accumulator_op(op, x, *args, **kwargs):
49
49
  return result
50
50
 
51
51
 
52
+ def logsumexp_real(a, axis=None, keepdims=False):
53
+ """Simplified logsumexp for real arrays without biases"""
54
+ from ... import tensor as mt
55
+
56
+ x = mt.tensor(a)
57
+ x_max = mt.amax(a, axis=axis, keepdims=True)
58
+ exp_x_shifted = mt.exp(x - x_max)
59
+ ret = mt.log(mt.sum(exp_x_shifted, axis=axis, keepdims=True)) + x_max
60
+ if keepdims:
61
+ return ret
62
+ return mt.squeeze(ret, axis=1)
63
+
64
+
52
65
  def _incremental_mean_and_var(
53
66
  X, last_mean, last_variance, last_sample_count, sample_weight=None
54
67
  ):
@@ -174,3 +187,27 @@ def _incremental_mean_and_var(
174
187
  updated_variance = updated_unnormalized_variance / updated_sample_count
175
188
 
176
189
  return updated_mean, updated_variance, updated_sample_count
190
+
191
+
192
+ def row_norms(X, squared=False):
193
+ """Row-wise (squared) Euclidean norm of X.
194
+
195
+ Performs no input validation.
196
+
197
+ Parameters
198
+ ----------
199
+ X : array_like
200
+ The input tensor
201
+ squared : bool, optional (default = False)
202
+ If True, return squared norms.
203
+
204
+ Returns
205
+ -------
206
+ array_like
207
+ The row-wise (squared) Euclidean norm of X.
208
+ """
209
+
210
+ norms = (X**2).sum(axis=1)
211
+ if not squared:
212
+ norms = mt.sqrt(norms)
213
+ return norms
@@ -0,0 +1,193 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Any, Dict, List, NamedTuple, Optional
16
+
17
+ from ... import opcodes
18
+ from ...core import ENTITY_TYPE, EntityData, OutputType
19
+ from ...core.operator import ObjectOperator
20
+ from ...serialization.serializables import (
21
+ AnyField,
22
+ BoolField,
23
+ DictField,
24
+ Int32Field,
25
+ StringField,
26
+ )
27
+ from ...utils import find_objects, replace_objects
28
+ from ..core import LearnOperatorMixin
29
+
30
+
31
+ class ToODPSModel(ObjectOperator, LearnOperatorMixin):
32
+ _op_type_ = opcodes.TO_ODPS_MODEL
33
+
34
+ model_name = StringField("model_name", default=None)
35
+ model_version = StringField("model_version", default=None)
36
+ training_info = AnyField("training_info", default=None)
37
+ params = AnyField("params", default=None)
38
+ format = StringField("format", default=None)
39
+ lifecycle = Int32Field("lifecycle", default=None)
40
+ version_lifecycle = Int32Field("version_lifecycle", default=None)
41
+ description = StringField("description", default=None)
42
+ version_description = StringField("version_description", default=None)
43
+ create_model = BoolField("create_model", default=True)
44
+ set_default_version = BoolField("set_default_version", default=True)
45
+ location = StringField("location", default=None)
46
+ storage_options = DictField("storage_options", default=None)
47
+
48
+ def __init__(self, **kw):
49
+ super().__init__(_output_types=[OutputType.object], **kw)
50
+
51
+ @classmethod
52
+ def _set_inputs(cls, op: "ToODPSModel", inputs: List[EntityData]):
53
+ super()._set_inputs(op, inputs)
54
+
55
+ if isinstance(op.training_info, ENTITY_TYPE):
56
+ has_training_info = True
57
+ op.training_info = inputs[0]
58
+ else:
59
+ has_training_info = False
60
+
61
+ tileables = find_objects([op.params], ENTITY_TYPE)
62
+ param_pos = int(has_training_info)
63
+ replaces = dict(zip(tileables, inputs[param_pos:]))
64
+ [op.params] = replace_objects([op.params], replaces)
65
+
66
+ def __call__(self, training_info, params):
67
+ inputs = []
68
+ if isinstance(training_info, ENTITY_TYPE):
69
+ inputs.append(training_info)
70
+
71
+ self.training_info = training_info
72
+ self.params = params
73
+ inputs.extend(find_objects([params], ENTITY_TYPE))
74
+ return self.new_tileable(inputs, shape=())
75
+
76
+
77
+ class ToODPSModelMixin:
78
+ class ODPSModelInfo(NamedTuple):
79
+ model_format: str
80
+ model_params: Any
81
+
82
+ def _get_odps_model_info(self) -> ODPSModelInfo:
83
+ raise NotImplementedError
84
+
85
+ def to_odps_model(
86
+ self,
87
+ model_name: str = None,
88
+ model_version: str = None,
89
+ schema: str = None,
90
+ project: str = None,
91
+ lifecycle: Optional[int] = None,
92
+ version_lifecycle: Optional[int] = None,
93
+ description: Optional[str] = None,
94
+ version_description: Optional[str] = None,
95
+ create_model: bool = True,
96
+ set_default_version: bool = False,
97
+ location: Optional[str] = None,
98
+ storage_options: Dict[str, Any] = None,
99
+ ):
100
+ """
101
+ Save trained model to MaxCompute.
102
+
103
+ Parameters
104
+ ----------
105
+ model_name : str, optional
106
+ Name of the model. Can be a fully qualified name with format
107
+ "project.schema.model" or just "model" if project and schema are
108
+ specified separately.
109
+ model_version : str, optional
110
+ Version of the model. If not provided, a default version will be used.
111
+ schema : str, optional
112
+ Schema name where the model will be stored. If not provided and
113
+ project is specified, "default" schema will be used.
114
+ project : str, optional
115
+ Project name where the model will be stored.
116
+ lifecycle : int, optional
117
+ Lifecycle of the model in days. After this period, the model will
118
+ be automatically deleted.
119
+ version_lifecycle : int, optional
120
+ Lifecycle of the model version in days. After this period, the
121
+ model version will be automatically deleted.
122
+ description : str, optional
123
+ Description of the model.
124
+ version_description : str, optional
125
+ Description of the model version.
126
+ create_model : bool, default True
127
+ Whether to create the model if it doesn't exist.
128
+ set_default_version : bool, default False
129
+ Whether to set this version as the default version of the model.
130
+ location : str, optional
131
+ Storage location for the model. If specified, the model can be stored
132
+ into a customized location. Can be an OSS path with format
133
+ oss://endpoint/bucket/path.
134
+ storage_options : dict, optional
135
+ Extra options for storage, such as role_arn or policy for OSS storage.
136
+
137
+ Returns
138
+ -------
139
+ Scalar
140
+ A scalar that can be executed to save the model.
141
+
142
+ Examples
143
+ --------
144
+ First we fit an XGBoost model.
145
+
146
+ >>> import maxframe.dataframe as md
147
+ >>> from maxframe.learn.datasets import make_classification
148
+ >>> from maxframe.learn.contrib.xgboost import XGBClassifier
149
+ >>> X, y = make_classification(1000, n_features=10, n_classes=2)
150
+ >>> cols = [f"f{idx}" for idx in range(10)]
151
+ >>> clf = XGBClassifier(n_estimators=10)
152
+ >>> X_df = md.DataFrame(X, columns=cols)
153
+ >>> clf.fit(X_df, y)
154
+
155
+ Trigger execution and save model with fully qualified name.
156
+
157
+ >>> clf.to_odps_model(model_name="project.schema.my_model",
158
+ ... model_version="v1.0").execute()
159
+
160
+ You can also save model with a customized path. Need to change `<my_bucket>`
161
+ and `<user_id>` into your own bucket and user ID.
162
+
163
+ >>> clf.to_odps_model(model_name="project.schema.my_model",
164
+ ... model_version="v1.0",
165
+ ... location="oss://oss-cn-shanghai.aliyuncs.com/<my_bucket>/model_name",
166
+ ... storage_options={
167
+ ... "role_arn": "acs:ram::<user_id>:role/aliyunodpsdefaultrole"
168
+ ... }).execute()
169
+ """
170
+ if "." not in model_name:
171
+ if project and not schema:
172
+ schema = "default"
173
+ if schema:
174
+ model_name = f"{schema}.{model_name}"
175
+ if project:
176
+ model_name = f"{project}.{model_name}"
177
+
178
+ model_info = self._get_odps_model_info()
179
+
180
+ op = ToODPSModel(
181
+ model_name=model_name,
182
+ model_version=model_version,
183
+ format=model_info.model_format,
184
+ lifecycle=lifecycle,
185
+ version_lifecycle=version_lifecycle,
186
+ description=description,
187
+ version_description=version_description,
188
+ create_model=create_model,
189
+ set_default_version=set_default_version,
190
+ location=location,
191
+ storage_options=storage_options,
192
+ )
193
+ return op(getattr(self, "training_info_"), model_info.model_params)
@@ -695,9 +695,9 @@ def _check_sample_weight(
695
695
  dtype = np.float64
696
696
 
697
697
  if sample_weight is None:
698
- sample_weight = np.ones(n_samples, dtype=dtype)
698
+ sample_weight = mt.ones(n_samples, dtype=dtype)
699
699
  elif isinstance(sample_weight, numbers.Number):
700
- sample_weight = np.full(n_samples, sample_weight, dtype=dtype)
700
+ sample_weight = mt.full(n_samples, sample_weight, dtype=dtype)
701
701
  else:
702
702
  if dtype is None:
703
703
  dtype = [np.float64, np.float32]
maxframe/lib/compat.py CHANGED
@@ -1,3 +1,5 @@
1
+ import asyncio
2
+ import functools
1
3
  from typing import TYPE_CHECKING, Callable, List, Sequence, Tuple, Union
2
4
 
3
5
  import numpy as np
@@ -143,3 +145,41 @@ def case_when(
143
145
  def patch_pandas():
144
146
  if not hasattr(pd.Series, "case_when"):
145
147
  pd.Series.case_when = case_when
148
+
149
+
150
+ class cached_property:
151
+ """
152
+ A property that is only computed once per instance and then replaces itself
153
+ with an ordinary attribute. Deleting the attribute resets the property.
154
+ Source: https://github.com/bottlepy/bottle/commit/fa7733e075da0d790d809aa3d2f53071897e6f76
155
+ """ # noqa
156
+
157
+ def __init__(self, func):
158
+ self.__doc__ = getattr(func, "__doc__")
159
+ self.func = func
160
+
161
+ def __get__(self, obj, cls):
162
+ if obj is None:
163
+ return self
164
+
165
+ if asyncio.iscoroutinefunction(self.func):
166
+ return self._wrap_in_coroutine(obj)
167
+
168
+ value = obj.__dict__[self.func.__name__] = self.func(obj)
169
+ return value
170
+
171
+ def _wrap_in_coroutine(self, obj):
172
+ @functools.wraps(obj)
173
+ def wrapper():
174
+ future = asyncio.ensure_future(self.func(obj))
175
+ obj.__dict__[self.func.__name__] = future
176
+ return future
177
+
178
+ return wrapper()
179
+
180
+
181
+ # isort: off
182
+ try:
183
+ from functools import cached_property # noqa: F811, F401
184
+ except ImportError:
185
+ pass
@@ -12,4 +12,19 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from .dtypes import ArrowDtype, dict_, is_list_dtype, is_map_dtype, list_
15
+ from .blob import (
16
+ ArrowBlobType,
17
+ ExternalBlobDtype,
18
+ ExternalBlobExtensionArray,
19
+ SolidBlob,
20
+ new_blob,
21
+ )
22
+ from .dtypes import (
23
+ ArrowDtype,
24
+ dict_,
25
+ is_list_dtype,
26
+ is_map_dtype,
27
+ is_struct_dtype,
28
+ list_,
29
+ struct_,
30
+ )