numpy 2.4.0__cp313-cp313t-musllinux_1_2_aarch64.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.
Files changed (915) hide show
  1. numpy/__config__.py +170 -0
  2. numpy/__config__.pyi +108 -0
  3. numpy/__init__.cython-30.pxd +1242 -0
  4. numpy/__init__.pxd +1155 -0
  5. numpy/__init__.py +942 -0
  6. numpy/__init__.pyi +6202 -0
  7. numpy/_array_api_info.py +346 -0
  8. numpy/_array_api_info.pyi +206 -0
  9. numpy/_configtool.py +39 -0
  10. numpy/_configtool.pyi +1 -0
  11. numpy/_core/__init__.py +201 -0
  12. numpy/_core/__init__.pyi +666 -0
  13. numpy/_core/_add_newdocs.py +7151 -0
  14. numpy/_core/_add_newdocs.pyi +2 -0
  15. numpy/_core/_add_newdocs_scalars.py +381 -0
  16. numpy/_core/_add_newdocs_scalars.pyi +16 -0
  17. numpy/_core/_asarray.py +130 -0
  18. numpy/_core/_asarray.pyi +43 -0
  19. numpy/_core/_dtype.py +366 -0
  20. numpy/_core/_dtype.pyi +56 -0
  21. numpy/_core/_dtype_ctypes.py +120 -0
  22. numpy/_core/_dtype_ctypes.pyi +83 -0
  23. numpy/_core/_exceptions.py +162 -0
  24. numpy/_core/_exceptions.pyi +54 -0
  25. numpy/_core/_internal.py +968 -0
  26. numpy/_core/_internal.pyi +61 -0
  27. numpy/_core/_methods.py +252 -0
  28. numpy/_core/_methods.pyi +22 -0
  29. numpy/_core/_multiarray_tests.cpython-313t-aarch64-linux-musl.so +0 -0
  30. numpy/_core/_multiarray_umath.cpython-313t-aarch64-linux-musl.so +0 -0
  31. numpy/_core/_operand_flag_tests.cpython-313t-aarch64-linux-musl.so +0 -0
  32. numpy/_core/_rational_tests.cpython-313t-aarch64-linux-musl.so +0 -0
  33. numpy/_core/_simd.cpython-313t-aarch64-linux-musl.so +0 -0
  34. numpy/_core/_simd.pyi +35 -0
  35. numpy/_core/_string_helpers.py +100 -0
  36. numpy/_core/_string_helpers.pyi +12 -0
  37. numpy/_core/_struct_ufunc_tests.cpython-313t-aarch64-linux-musl.so +0 -0
  38. numpy/_core/_type_aliases.py +131 -0
  39. numpy/_core/_type_aliases.pyi +86 -0
  40. numpy/_core/_ufunc_config.py +515 -0
  41. numpy/_core/_ufunc_config.pyi +69 -0
  42. numpy/_core/_umath_tests.cpython-313t-aarch64-linux-musl.so +0 -0
  43. numpy/_core/_umath_tests.pyi +47 -0
  44. numpy/_core/arrayprint.py +1779 -0
  45. numpy/_core/arrayprint.pyi +158 -0
  46. numpy/_core/cversions.py +13 -0
  47. numpy/_core/defchararray.py +1414 -0
  48. numpy/_core/defchararray.pyi +1150 -0
  49. numpy/_core/einsumfunc.py +1650 -0
  50. numpy/_core/einsumfunc.pyi +184 -0
  51. numpy/_core/fromnumeric.py +4233 -0
  52. numpy/_core/fromnumeric.pyi +1735 -0
  53. numpy/_core/function_base.py +547 -0
  54. numpy/_core/function_base.pyi +276 -0
  55. numpy/_core/getlimits.py +462 -0
  56. numpy/_core/getlimits.pyi +124 -0
  57. numpy/_core/include/numpy/__multiarray_api.c +376 -0
  58. numpy/_core/include/numpy/__multiarray_api.h +1628 -0
  59. numpy/_core/include/numpy/__ufunc_api.c +55 -0
  60. numpy/_core/include/numpy/__ufunc_api.h +349 -0
  61. numpy/_core/include/numpy/_neighborhood_iterator_imp.h +90 -0
  62. numpy/_core/include/numpy/_numpyconfig.h +33 -0
  63. numpy/_core/include/numpy/_public_dtype_api_table.h +86 -0
  64. numpy/_core/include/numpy/arrayobject.h +7 -0
  65. numpy/_core/include/numpy/arrayscalars.h +198 -0
  66. numpy/_core/include/numpy/dtype_api.h +547 -0
  67. numpy/_core/include/numpy/halffloat.h +70 -0
  68. numpy/_core/include/numpy/ndarrayobject.h +304 -0
  69. numpy/_core/include/numpy/ndarraytypes.h +1982 -0
  70. numpy/_core/include/numpy/npy_2_compat.h +249 -0
  71. numpy/_core/include/numpy/npy_2_complexcompat.h +28 -0
  72. numpy/_core/include/numpy/npy_3kcompat.h +374 -0
  73. numpy/_core/include/numpy/npy_common.h +989 -0
  74. numpy/_core/include/numpy/npy_cpu.h +126 -0
  75. numpy/_core/include/numpy/npy_endian.h +79 -0
  76. numpy/_core/include/numpy/npy_math.h +602 -0
  77. numpy/_core/include/numpy/npy_no_deprecated_api.h +20 -0
  78. numpy/_core/include/numpy/npy_os.h +42 -0
  79. numpy/_core/include/numpy/numpyconfig.h +185 -0
  80. numpy/_core/include/numpy/random/LICENSE.txt +21 -0
  81. numpy/_core/include/numpy/random/bitgen.h +20 -0
  82. numpy/_core/include/numpy/random/distributions.h +209 -0
  83. numpy/_core/include/numpy/random/libdivide.h +2079 -0
  84. numpy/_core/include/numpy/ufuncobject.h +343 -0
  85. numpy/_core/include/numpy/utils.h +37 -0
  86. numpy/_core/lib/libnpymath.a +0 -0
  87. numpy/_core/lib/npy-pkg-config/mlib.ini +12 -0
  88. numpy/_core/lib/npy-pkg-config/npymath.ini +20 -0
  89. numpy/_core/lib/pkgconfig/numpy.pc +7 -0
  90. numpy/_core/memmap.py +363 -0
  91. numpy/_core/memmap.pyi +3 -0
  92. numpy/_core/multiarray.py +1740 -0
  93. numpy/_core/multiarray.pyi +1316 -0
  94. numpy/_core/numeric.py +2758 -0
  95. numpy/_core/numeric.pyi +1276 -0
  96. numpy/_core/numerictypes.py +633 -0
  97. numpy/_core/numerictypes.pyi +196 -0
  98. numpy/_core/overrides.py +188 -0
  99. numpy/_core/overrides.pyi +47 -0
  100. numpy/_core/printoptions.py +32 -0
  101. numpy/_core/printoptions.pyi +28 -0
  102. numpy/_core/records.py +1088 -0
  103. numpy/_core/records.pyi +340 -0
  104. numpy/_core/shape_base.py +996 -0
  105. numpy/_core/shape_base.pyi +182 -0
  106. numpy/_core/strings.py +1813 -0
  107. numpy/_core/strings.pyi +536 -0
  108. numpy/_core/tests/_locales.py +72 -0
  109. numpy/_core/tests/_natype.py +144 -0
  110. numpy/_core/tests/data/astype_copy.pkl +0 -0
  111. numpy/_core/tests/data/generate_umath_validation_data.cpp +170 -0
  112. numpy/_core/tests/data/recarray_from_file.fits +0 -0
  113. numpy/_core/tests/data/umath-validation-set-README.txt +15 -0
  114. numpy/_core/tests/data/umath-validation-set-arccos.csv +1429 -0
  115. numpy/_core/tests/data/umath-validation-set-arccosh.csv +1429 -0
  116. numpy/_core/tests/data/umath-validation-set-arcsin.csv +1429 -0
  117. numpy/_core/tests/data/umath-validation-set-arcsinh.csv +1429 -0
  118. numpy/_core/tests/data/umath-validation-set-arctan.csv +1429 -0
  119. numpy/_core/tests/data/umath-validation-set-arctanh.csv +1429 -0
  120. numpy/_core/tests/data/umath-validation-set-cbrt.csv +1429 -0
  121. numpy/_core/tests/data/umath-validation-set-cos.csv +1375 -0
  122. numpy/_core/tests/data/umath-validation-set-cosh.csv +1429 -0
  123. numpy/_core/tests/data/umath-validation-set-exp.csv +412 -0
  124. numpy/_core/tests/data/umath-validation-set-exp2.csv +1429 -0
  125. numpy/_core/tests/data/umath-validation-set-expm1.csv +1429 -0
  126. numpy/_core/tests/data/umath-validation-set-log.csv +271 -0
  127. numpy/_core/tests/data/umath-validation-set-log10.csv +1629 -0
  128. numpy/_core/tests/data/umath-validation-set-log1p.csv +1429 -0
  129. numpy/_core/tests/data/umath-validation-set-log2.csv +1629 -0
  130. numpy/_core/tests/data/umath-validation-set-sin.csv +1370 -0
  131. numpy/_core/tests/data/umath-validation-set-sinh.csv +1429 -0
  132. numpy/_core/tests/data/umath-validation-set-tan.csv +1429 -0
  133. numpy/_core/tests/data/umath-validation-set-tanh.csv +1429 -0
  134. numpy/_core/tests/examples/cython/checks.pyx +373 -0
  135. numpy/_core/tests/examples/cython/meson.build +43 -0
  136. numpy/_core/tests/examples/cython/setup.py +39 -0
  137. numpy/_core/tests/examples/limited_api/limited_api1.c +17 -0
  138. numpy/_core/tests/examples/limited_api/limited_api2.pyx +11 -0
  139. numpy/_core/tests/examples/limited_api/limited_api_latest.c +19 -0
  140. numpy/_core/tests/examples/limited_api/meson.build +59 -0
  141. numpy/_core/tests/examples/limited_api/setup.py +24 -0
  142. numpy/_core/tests/test__exceptions.py +90 -0
  143. numpy/_core/tests/test_abc.py +54 -0
  144. numpy/_core/tests/test_api.py +655 -0
  145. numpy/_core/tests/test_argparse.py +90 -0
  146. numpy/_core/tests/test_array_api_info.py +113 -0
  147. numpy/_core/tests/test_array_coercion.py +928 -0
  148. numpy/_core/tests/test_array_interface.py +222 -0
  149. numpy/_core/tests/test_arraymethod.py +84 -0
  150. numpy/_core/tests/test_arrayobject.py +75 -0
  151. numpy/_core/tests/test_arrayprint.py +1324 -0
  152. numpy/_core/tests/test_casting_floatingpoint_errors.py +154 -0
  153. numpy/_core/tests/test_casting_unittests.py +955 -0
  154. numpy/_core/tests/test_conversion_utils.py +209 -0
  155. numpy/_core/tests/test_cpu_dispatcher.py +48 -0
  156. numpy/_core/tests/test_cpu_features.py +450 -0
  157. numpy/_core/tests/test_custom_dtypes.py +393 -0
  158. numpy/_core/tests/test_cython.py +352 -0
  159. numpy/_core/tests/test_datetime.py +2792 -0
  160. numpy/_core/tests/test_defchararray.py +858 -0
  161. numpy/_core/tests/test_deprecations.py +460 -0
  162. numpy/_core/tests/test_dlpack.py +190 -0
  163. numpy/_core/tests/test_dtype.py +2110 -0
  164. numpy/_core/tests/test_einsum.py +1351 -0
  165. numpy/_core/tests/test_errstate.py +131 -0
  166. numpy/_core/tests/test_extint128.py +217 -0
  167. numpy/_core/tests/test_finfo.py +86 -0
  168. numpy/_core/tests/test_function_base.py +504 -0
  169. numpy/_core/tests/test_getlimits.py +171 -0
  170. numpy/_core/tests/test_half.py +593 -0
  171. numpy/_core/tests/test_hashtable.py +36 -0
  172. numpy/_core/tests/test_indexerrors.py +122 -0
  173. numpy/_core/tests/test_indexing.py +1692 -0
  174. numpy/_core/tests/test_item_selection.py +167 -0
  175. numpy/_core/tests/test_limited_api.py +102 -0
  176. numpy/_core/tests/test_longdouble.py +370 -0
  177. numpy/_core/tests/test_mem_overlap.py +933 -0
  178. numpy/_core/tests/test_mem_policy.py +453 -0
  179. numpy/_core/tests/test_memmap.py +248 -0
  180. numpy/_core/tests/test_multiarray.py +11008 -0
  181. numpy/_core/tests/test_multiprocessing.py +55 -0
  182. numpy/_core/tests/test_multithreading.py +353 -0
  183. numpy/_core/tests/test_nditer.py +3533 -0
  184. numpy/_core/tests/test_nep50_promotions.py +287 -0
  185. numpy/_core/tests/test_numeric.py +4295 -0
  186. numpy/_core/tests/test_numerictypes.py +650 -0
  187. numpy/_core/tests/test_overrides.py +800 -0
  188. numpy/_core/tests/test_print.py +202 -0
  189. numpy/_core/tests/test_protocols.py +46 -0
  190. numpy/_core/tests/test_records.py +544 -0
  191. numpy/_core/tests/test_regression.py +2677 -0
  192. numpy/_core/tests/test_scalar_ctors.py +203 -0
  193. numpy/_core/tests/test_scalar_methods.py +328 -0
  194. numpy/_core/tests/test_scalarbuffer.py +153 -0
  195. numpy/_core/tests/test_scalarinherit.py +105 -0
  196. numpy/_core/tests/test_scalarmath.py +1168 -0
  197. numpy/_core/tests/test_scalarprint.py +403 -0
  198. numpy/_core/tests/test_shape_base.py +904 -0
  199. numpy/_core/tests/test_simd.py +1345 -0
  200. numpy/_core/tests/test_simd_module.py +105 -0
  201. numpy/_core/tests/test_stringdtype.py +1855 -0
  202. numpy/_core/tests/test_strings.py +1515 -0
  203. numpy/_core/tests/test_ufunc.py +3405 -0
  204. numpy/_core/tests/test_umath.py +4962 -0
  205. numpy/_core/tests/test_umath_accuracy.py +132 -0
  206. numpy/_core/tests/test_umath_complex.py +631 -0
  207. numpy/_core/tests/test_unicode.py +369 -0
  208. numpy/_core/umath.py +60 -0
  209. numpy/_core/umath.pyi +232 -0
  210. numpy/_distributor_init.py +15 -0
  211. numpy/_distributor_init.pyi +1 -0
  212. numpy/_expired_attrs_2_0.py +78 -0
  213. numpy/_expired_attrs_2_0.pyi +61 -0
  214. numpy/_globals.py +121 -0
  215. numpy/_globals.pyi +17 -0
  216. numpy/_pyinstaller/__init__.py +0 -0
  217. numpy/_pyinstaller/__init__.pyi +0 -0
  218. numpy/_pyinstaller/hook-numpy.py +36 -0
  219. numpy/_pyinstaller/hook-numpy.pyi +6 -0
  220. numpy/_pyinstaller/tests/__init__.py +16 -0
  221. numpy/_pyinstaller/tests/pyinstaller-smoke.py +32 -0
  222. numpy/_pyinstaller/tests/test_pyinstaller.py +35 -0
  223. numpy/_pytesttester.py +201 -0
  224. numpy/_pytesttester.pyi +18 -0
  225. numpy/_typing/__init__.py +173 -0
  226. numpy/_typing/_add_docstring.py +153 -0
  227. numpy/_typing/_array_like.py +106 -0
  228. numpy/_typing/_char_codes.py +213 -0
  229. numpy/_typing/_dtype_like.py +114 -0
  230. numpy/_typing/_extended_precision.py +15 -0
  231. numpy/_typing/_nbit.py +19 -0
  232. numpy/_typing/_nbit_base.py +94 -0
  233. numpy/_typing/_nbit_base.pyi +39 -0
  234. numpy/_typing/_nested_sequence.py +79 -0
  235. numpy/_typing/_scalars.py +20 -0
  236. numpy/_typing/_shape.py +8 -0
  237. numpy/_typing/_ufunc.py +7 -0
  238. numpy/_typing/_ufunc.pyi +975 -0
  239. numpy/_utils/__init__.py +95 -0
  240. numpy/_utils/__init__.pyi +28 -0
  241. numpy/_utils/_convertions.py +18 -0
  242. numpy/_utils/_convertions.pyi +4 -0
  243. numpy/_utils/_inspect.py +192 -0
  244. numpy/_utils/_inspect.pyi +70 -0
  245. numpy/_utils/_pep440.py +486 -0
  246. numpy/_utils/_pep440.pyi +118 -0
  247. numpy/char/__init__.py +2 -0
  248. numpy/char/__init__.pyi +111 -0
  249. numpy/conftest.py +248 -0
  250. numpy/core/__init__.py +33 -0
  251. numpy/core/__init__.pyi +0 -0
  252. numpy/core/_dtype.py +10 -0
  253. numpy/core/_dtype.pyi +0 -0
  254. numpy/core/_dtype_ctypes.py +10 -0
  255. numpy/core/_dtype_ctypes.pyi +0 -0
  256. numpy/core/_internal.py +27 -0
  257. numpy/core/_multiarray_umath.py +57 -0
  258. numpy/core/_utils.py +21 -0
  259. numpy/core/arrayprint.py +10 -0
  260. numpy/core/defchararray.py +10 -0
  261. numpy/core/einsumfunc.py +10 -0
  262. numpy/core/fromnumeric.py +10 -0
  263. numpy/core/function_base.py +10 -0
  264. numpy/core/getlimits.py +10 -0
  265. numpy/core/multiarray.py +25 -0
  266. numpy/core/numeric.py +12 -0
  267. numpy/core/numerictypes.py +10 -0
  268. numpy/core/overrides.py +10 -0
  269. numpy/core/overrides.pyi +7 -0
  270. numpy/core/records.py +10 -0
  271. numpy/core/shape_base.py +10 -0
  272. numpy/core/umath.py +10 -0
  273. numpy/ctypeslib/__init__.py +13 -0
  274. numpy/ctypeslib/__init__.pyi +15 -0
  275. numpy/ctypeslib/_ctypeslib.py +603 -0
  276. numpy/ctypeslib/_ctypeslib.pyi +236 -0
  277. numpy/doc/ufuncs.py +138 -0
  278. numpy/dtypes.py +41 -0
  279. numpy/dtypes.pyi +630 -0
  280. numpy/exceptions.py +246 -0
  281. numpy/exceptions.pyi +27 -0
  282. numpy/f2py/__init__.py +86 -0
  283. numpy/f2py/__init__.pyi +5 -0
  284. numpy/f2py/__main__.py +5 -0
  285. numpy/f2py/__version__.py +1 -0
  286. numpy/f2py/__version__.pyi +1 -0
  287. numpy/f2py/_backends/__init__.py +9 -0
  288. numpy/f2py/_backends/__init__.pyi +5 -0
  289. numpy/f2py/_backends/_backend.py +44 -0
  290. numpy/f2py/_backends/_backend.pyi +46 -0
  291. numpy/f2py/_backends/_distutils.py +76 -0
  292. numpy/f2py/_backends/_distutils.pyi +13 -0
  293. numpy/f2py/_backends/_meson.py +244 -0
  294. numpy/f2py/_backends/_meson.pyi +62 -0
  295. numpy/f2py/_backends/meson.build.template +58 -0
  296. numpy/f2py/_isocbind.py +62 -0
  297. numpy/f2py/_isocbind.pyi +13 -0
  298. numpy/f2py/_src_pyf.py +247 -0
  299. numpy/f2py/_src_pyf.pyi +28 -0
  300. numpy/f2py/auxfuncs.py +1004 -0
  301. numpy/f2py/auxfuncs.pyi +262 -0
  302. numpy/f2py/capi_maps.py +811 -0
  303. numpy/f2py/capi_maps.pyi +33 -0
  304. numpy/f2py/cb_rules.py +665 -0
  305. numpy/f2py/cb_rules.pyi +17 -0
  306. numpy/f2py/cfuncs.py +1563 -0
  307. numpy/f2py/cfuncs.pyi +31 -0
  308. numpy/f2py/common_rules.py +143 -0
  309. numpy/f2py/common_rules.pyi +9 -0
  310. numpy/f2py/crackfortran.py +3725 -0
  311. numpy/f2py/crackfortran.pyi +266 -0
  312. numpy/f2py/diagnose.py +149 -0
  313. numpy/f2py/diagnose.pyi +1 -0
  314. numpy/f2py/f2py2e.py +788 -0
  315. numpy/f2py/f2py2e.pyi +74 -0
  316. numpy/f2py/f90mod_rules.py +269 -0
  317. numpy/f2py/f90mod_rules.pyi +16 -0
  318. numpy/f2py/func2subr.py +329 -0
  319. numpy/f2py/func2subr.pyi +7 -0
  320. numpy/f2py/rules.py +1629 -0
  321. numpy/f2py/rules.pyi +41 -0
  322. numpy/f2py/setup.cfg +3 -0
  323. numpy/f2py/src/fortranobject.c +1436 -0
  324. numpy/f2py/src/fortranobject.h +173 -0
  325. numpy/f2py/symbolic.py +1518 -0
  326. numpy/f2py/symbolic.pyi +219 -0
  327. numpy/f2py/tests/__init__.py +16 -0
  328. numpy/f2py/tests/src/abstract_interface/foo.f90 +34 -0
  329. numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90 +6 -0
  330. numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c +235 -0
  331. numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap +1 -0
  332. numpy/f2py/tests/src/assumed_shape/foo_free.f90 +34 -0
  333. numpy/f2py/tests/src/assumed_shape/foo_mod.f90 +41 -0
  334. numpy/f2py/tests/src/assumed_shape/foo_use.f90 +19 -0
  335. numpy/f2py/tests/src/assumed_shape/precision.f90 +4 -0
  336. numpy/f2py/tests/src/block_docstring/foo.f +6 -0
  337. numpy/f2py/tests/src/callback/foo.f +62 -0
  338. numpy/f2py/tests/src/callback/gh17797.f90 +7 -0
  339. numpy/f2py/tests/src/callback/gh18335.f90 +17 -0
  340. numpy/f2py/tests/src/callback/gh25211.f +10 -0
  341. numpy/f2py/tests/src/callback/gh25211.pyf +18 -0
  342. numpy/f2py/tests/src/callback/gh26681.f90 +18 -0
  343. numpy/f2py/tests/src/cli/gh_22819.pyf +6 -0
  344. numpy/f2py/tests/src/cli/hi77.f +3 -0
  345. numpy/f2py/tests/src/cli/hiworld.f90 +3 -0
  346. numpy/f2py/tests/src/common/block.f +11 -0
  347. numpy/f2py/tests/src/common/gh19161.f90 +10 -0
  348. numpy/f2py/tests/src/crackfortran/accesstype.f90 +13 -0
  349. numpy/f2py/tests/src/crackfortran/common_with_division.f +17 -0
  350. numpy/f2py/tests/src/crackfortran/data_common.f +8 -0
  351. numpy/f2py/tests/src/crackfortran/data_multiplier.f +5 -0
  352. numpy/f2py/tests/src/crackfortran/data_stmts.f90 +20 -0
  353. numpy/f2py/tests/src/crackfortran/data_with_comments.f +8 -0
  354. numpy/f2py/tests/src/crackfortran/foo_deps.f90 +6 -0
  355. numpy/f2py/tests/src/crackfortran/gh15035.f +16 -0
  356. numpy/f2py/tests/src/crackfortran/gh17859.f +12 -0
  357. numpy/f2py/tests/src/crackfortran/gh22648.pyf +7 -0
  358. numpy/f2py/tests/src/crackfortran/gh23533.f +5 -0
  359. numpy/f2py/tests/src/crackfortran/gh23598.f90 +4 -0
  360. numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 +11 -0
  361. numpy/f2py/tests/src/crackfortran/gh23879.f90 +20 -0
  362. numpy/f2py/tests/src/crackfortran/gh27697.f90 +12 -0
  363. numpy/f2py/tests/src/crackfortran/gh2848.f90 +13 -0
  364. numpy/f2py/tests/src/crackfortran/operators.f90 +49 -0
  365. numpy/f2py/tests/src/crackfortran/privatemod.f90 +11 -0
  366. numpy/f2py/tests/src/crackfortran/publicmod.f90 +10 -0
  367. numpy/f2py/tests/src/crackfortran/pubprivmod.f90 +10 -0
  368. numpy/f2py/tests/src/crackfortran/unicode_comment.f90 +4 -0
  369. numpy/f2py/tests/src/f2cmap/.f2py_f2cmap +1 -0
  370. numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90 +9 -0
  371. numpy/f2py/tests/src/isocintrin/isoCtests.f90 +34 -0
  372. numpy/f2py/tests/src/kind/foo.f90 +20 -0
  373. numpy/f2py/tests/src/mixed/foo.f +5 -0
  374. numpy/f2py/tests/src/mixed/foo_fixed.f90 +8 -0
  375. numpy/f2py/tests/src/mixed/foo_free.f90 +8 -0
  376. numpy/f2py/tests/src/modules/gh25337/data.f90 +8 -0
  377. numpy/f2py/tests/src/modules/gh25337/use_data.f90 +6 -0
  378. numpy/f2py/tests/src/modules/gh26920/two_mods_with_no_public_entities.f90 +21 -0
  379. numpy/f2py/tests/src/modules/gh26920/two_mods_with_one_public_routine.f90 +21 -0
  380. numpy/f2py/tests/src/modules/module_data_docstring.f90 +12 -0
  381. numpy/f2py/tests/src/modules/use_modules.f90 +20 -0
  382. numpy/f2py/tests/src/negative_bounds/issue_20853.f90 +7 -0
  383. numpy/f2py/tests/src/parameter/constant_array.f90 +45 -0
  384. numpy/f2py/tests/src/parameter/constant_both.f90 +57 -0
  385. numpy/f2py/tests/src/parameter/constant_compound.f90 +15 -0
  386. numpy/f2py/tests/src/parameter/constant_integer.f90 +22 -0
  387. numpy/f2py/tests/src/parameter/constant_non_compound.f90 +23 -0
  388. numpy/f2py/tests/src/parameter/constant_real.f90 +23 -0
  389. numpy/f2py/tests/src/quoted_character/foo.f +14 -0
  390. numpy/f2py/tests/src/regression/AB.inc +1 -0
  391. numpy/f2py/tests/src/regression/assignOnlyModule.f90 +25 -0
  392. numpy/f2py/tests/src/regression/datonly.f90 +17 -0
  393. numpy/f2py/tests/src/regression/f77comments.f +26 -0
  394. numpy/f2py/tests/src/regression/f77fixedform.f95 +5 -0
  395. numpy/f2py/tests/src/regression/f90continuation.f90 +9 -0
  396. numpy/f2py/tests/src/regression/incfile.f90 +5 -0
  397. numpy/f2py/tests/src/regression/inout.f90 +9 -0
  398. numpy/f2py/tests/src/regression/lower_f2py_fortran.f90 +5 -0
  399. numpy/f2py/tests/src/regression/mod_derived_types.f90 +23 -0
  400. numpy/f2py/tests/src/return_character/foo77.f +45 -0
  401. numpy/f2py/tests/src/return_character/foo90.f90 +48 -0
  402. numpy/f2py/tests/src/return_complex/foo77.f +45 -0
  403. numpy/f2py/tests/src/return_complex/foo90.f90 +48 -0
  404. numpy/f2py/tests/src/return_integer/foo77.f +56 -0
  405. numpy/f2py/tests/src/return_integer/foo90.f90 +59 -0
  406. numpy/f2py/tests/src/return_logical/foo77.f +56 -0
  407. numpy/f2py/tests/src/return_logical/foo90.f90 +59 -0
  408. numpy/f2py/tests/src/return_real/foo77.f +45 -0
  409. numpy/f2py/tests/src/return_real/foo90.f90 +48 -0
  410. numpy/f2py/tests/src/routines/funcfortranname.f +5 -0
  411. numpy/f2py/tests/src/routines/funcfortranname.pyf +11 -0
  412. numpy/f2py/tests/src/routines/subrout.f +4 -0
  413. numpy/f2py/tests/src/routines/subrout.pyf +10 -0
  414. numpy/f2py/tests/src/size/foo.f90 +44 -0
  415. numpy/f2py/tests/src/string/char.f90 +29 -0
  416. numpy/f2py/tests/src/string/fixed_string.f90 +34 -0
  417. numpy/f2py/tests/src/string/gh24008.f +8 -0
  418. numpy/f2py/tests/src/string/gh24662.f90 +7 -0
  419. numpy/f2py/tests/src/string/gh25286.f90 +14 -0
  420. numpy/f2py/tests/src/string/gh25286.pyf +12 -0
  421. numpy/f2py/tests/src/string/gh25286_bc.pyf +12 -0
  422. numpy/f2py/tests/src/string/scalar_string.f90 +9 -0
  423. numpy/f2py/tests/src/string/string.f +12 -0
  424. numpy/f2py/tests/src/value_attrspec/gh21665.f90 +9 -0
  425. numpy/f2py/tests/test_abstract_interface.py +26 -0
  426. numpy/f2py/tests/test_array_from_pyobj.py +678 -0
  427. numpy/f2py/tests/test_assumed_shape.py +50 -0
  428. numpy/f2py/tests/test_block_docstring.py +20 -0
  429. numpy/f2py/tests/test_callback.py +263 -0
  430. numpy/f2py/tests/test_character.py +641 -0
  431. numpy/f2py/tests/test_common.py +23 -0
  432. numpy/f2py/tests/test_crackfortran.py +421 -0
  433. numpy/f2py/tests/test_data.py +71 -0
  434. numpy/f2py/tests/test_docs.py +66 -0
  435. numpy/f2py/tests/test_f2cmap.py +17 -0
  436. numpy/f2py/tests/test_f2py2e.py +983 -0
  437. numpy/f2py/tests/test_isoc.py +56 -0
  438. numpy/f2py/tests/test_kind.py +52 -0
  439. numpy/f2py/tests/test_mixed.py +35 -0
  440. numpy/f2py/tests/test_modules.py +83 -0
  441. numpy/f2py/tests/test_parameter.py +129 -0
  442. numpy/f2py/tests/test_pyf_src.py +43 -0
  443. numpy/f2py/tests/test_quoted_character.py +18 -0
  444. numpy/f2py/tests/test_regression.py +187 -0
  445. numpy/f2py/tests/test_return_character.py +48 -0
  446. numpy/f2py/tests/test_return_complex.py +67 -0
  447. numpy/f2py/tests/test_return_integer.py +55 -0
  448. numpy/f2py/tests/test_return_logical.py +65 -0
  449. numpy/f2py/tests/test_return_real.py +109 -0
  450. numpy/f2py/tests/test_routines.py +29 -0
  451. numpy/f2py/tests/test_semicolon_split.py +75 -0
  452. numpy/f2py/tests/test_size.py +45 -0
  453. numpy/f2py/tests/test_string.py +100 -0
  454. numpy/f2py/tests/test_symbolic.py +500 -0
  455. numpy/f2py/tests/test_value_attrspec.py +15 -0
  456. numpy/f2py/tests/util.py +442 -0
  457. numpy/f2py/use_rules.py +99 -0
  458. numpy/f2py/use_rules.pyi +9 -0
  459. numpy/fft/__init__.py +213 -0
  460. numpy/fft/__init__.pyi +38 -0
  461. numpy/fft/_helper.py +235 -0
  462. numpy/fft/_helper.pyi +44 -0
  463. numpy/fft/_pocketfft.py +1693 -0
  464. numpy/fft/_pocketfft.pyi +137 -0
  465. numpy/fft/_pocketfft_umath.cpython-313t-aarch64-linux-musl.so +0 -0
  466. numpy/fft/tests/__init__.py +0 -0
  467. numpy/fft/tests/test_helper.py +167 -0
  468. numpy/fft/tests/test_pocketfft.py +589 -0
  469. numpy/lib/__init__.py +97 -0
  470. numpy/lib/__init__.pyi +52 -0
  471. numpy/lib/_array_utils_impl.py +62 -0
  472. numpy/lib/_array_utils_impl.pyi +10 -0
  473. numpy/lib/_arraypad_impl.py +926 -0
  474. numpy/lib/_arraypad_impl.pyi +88 -0
  475. numpy/lib/_arraysetops_impl.py +1158 -0
  476. numpy/lib/_arraysetops_impl.pyi +462 -0
  477. numpy/lib/_arrayterator_impl.py +224 -0
  478. numpy/lib/_arrayterator_impl.pyi +45 -0
  479. numpy/lib/_datasource.py +700 -0
  480. numpy/lib/_datasource.pyi +30 -0
  481. numpy/lib/_format_impl.py +1036 -0
  482. numpy/lib/_format_impl.pyi +56 -0
  483. numpy/lib/_function_base_impl.py +5758 -0
  484. numpy/lib/_function_base_impl.pyi +2324 -0
  485. numpy/lib/_histograms_impl.py +1085 -0
  486. numpy/lib/_histograms_impl.pyi +40 -0
  487. numpy/lib/_index_tricks_impl.py +1048 -0
  488. numpy/lib/_index_tricks_impl.pyi +267 -0
  489. numpy/lib/_iotools.py +900 -0
  490. numpy/lib/_iotools.pyi +116 -0
  491. numpy/lib/_nanfunctions_impl.py +2001 -0
  492. numpy/lib/_nanfunctions_impl.pyi +48 -0
  493. numpy/lib/_npyio_impl.py +2583 -0
  494. numpy/lib/_npyio_impl.pyi +299 -0
  495. numpy/lib/_polynomial_impl.py +1465 -0
  496. numpy/lib/_polynomial_impl.pyi +338 -0
  497. numpy/lib/_scimath_impl.py +642 -0
  498. numpy/lib/_scimath_impl.pyi +93 -0
  499. numpy/lib/_shape_base_impl.py +1289 -0
  500. numpy/lib/_shape_base_impl.pyi +236 -0
  501. numpy/lib/_stride_tricks_impl.py +582 -0
  502. numpy/lib/_stride_tricks_impl.pyi +73 -0
  503. numpy/lib/_twodim_base_impl.py +1201 -0
  504. numpy/lib/_twodim_base_impl.pyi +408 -0
  505. numpy/lib/_type_check_impl.py +710 -0
  506. numpy/lib/_type_check_impl.pyi +348 -0
  507. numpy/lib/_ufunclike_impl.py +199 -0
  508. numpy/lib/_ufunclike_impl.pyi +60 -0
  509. numpy/lib/_user_array_impl.py +310 -0
  510. numpy/lib/_user_array_impl.pyi +226 -0
  511. numpy/lib/_utils_impl.py +784 -0
  512. numpy/lib/_utils_impl.pyi +22 -0
  513. numpy/lib/_version.py +153 -0
  514. numpy/lib/_version.pyi +17 -0
  515. numpy/lib/array_utils.py +7 -0
  516. numpy/lib/array_utils.pyi +6 -0
  517. numpy/lib/format.py +24 -0
  518. numpy/lib/format.pyi +24 -0
  519. numpy/lib/introspect.py +94 -0
  520. numpy/lib/introspect.pyi +3 -0
  521. numpy/lib/mixins.py +180 -0
  522. numpy/lib/mixins.pyi +78 -0
  523. numpy/lib/npyio.py +1 -0
  524. numpy/lib/npyio.pyi +5 -0
  525. numpy/lib/recfunctions.py +1681 -0
  526. numpy/lib/recfunctions.pyi +444 -0
  527. numpy/lib/scimath.py +13 -0
  528. numpy/lib/scimath.pyi +12 -0
  529. numpy/lib/stride_tricks.py +1 -0
  530. numpy/lib/stride_tricks.pyi +4 -0
  531. numpy/lib/tests/__init__.py +0 -0
  532. numpy/lib/tests/data/py2-np0-objarr.npy +0 -0
  533. numpy/lib/tests/data/py2-objarr.npy +0 -0
  534. numpy/lib/tests/data/py2-objarr.npz +0 -0
  535. numpy/lib/tests/data/py3-objarr.npy +0 -0
  536. numpy/lib/tests/data/py3-objarr.npz +0 -0
  537. numpy/lib/tests/data/python3.npy +0 -0
  538. numpy/lib/tests/data/win64python2.npy +0 -0
  539. numpy/lib/tests/test__datasource.py +328 -0
  540. numpy/lib/tests/test__iotools.py +358 -0
  541. numpy/lib/tests/test__version.py +64 -0
  542. numpy/lib/tests/test_array_utils.py +32 -0
  543. numpy/lib/tests/test_arraypad.py +1427 -0
  544. numpy/lib/tests/test_arraysetops.py +1302 -0
  545. numpy/lib/tests/test_arrayterator.py +45 -0
  546. numpy/lib/tests/test_format.py +1054 -0
  547. numpy/lib/tests/test_function_base.py +4705 -0
  548. numpy/lib/tests/test_histograms.py +855 -0
  549. numpy/lib/tests/test_index_tricks.py +693 -0
  550. numpy/lib/tests/test_io.py +2857 -0
  551. numpy/lib/tests/test_loadtxt.py +1099 -0
  552. numpy/lib/tests/test_mixins.py +215 -0
  553. numpy/lib/tests/test_nanfunctions.py +1438 -0
  554. numpy/lib/tests/test_packbits.py +376 -0
  555. numpy/lib/tests/test_polynomial.py +325 -0
  556. numpy/lib/tests/test_recfunctions.py +1042 -0
  557. numpy/lib/tests/test_regression.py +231 -0
  558. numpy/lib/tests/test_shape_base.py +813 -0
  559. numpy/lib/tests/test_stride_tricks.py +655 -0
  560. numpy/lib/tests/test_twodim_base.py +559 -0
  561. numpy/lib/tests/test_type_check.py +473 -0
  562. numpy/lib/tests/test_ufunclike.py +97 -0
  563. numpy/lib/tests/test_utils.py +80 -0
  564. numpy/lib/user_array.py +1 -0
  565. numpy/lib/user_array.pyi +1 -0
  566. numpy/linalg/__init__.py +95 -0
  567. numpy/linalg/__init__.pyi +71 -0
  568. numpy/linalg/_linalg.py +3657 -0
  569. numpy/linalg/_linalg.pyi +548 -0
  570. numpy/linalg/_umath_linalg.cpython-313t-aarch64-linux-musl.so +0 -0
  571. numpy/linalg/_umath_linalg.pyi +60 -0
  572. numpy/linalg/lapack_lite.cpython-313t-aarch64-linux-musl.so +0 -0
  573. numpy/linalg/lapack_lite.pyi +143 -0
  574. numpy/linalg/tests/__init__.py +0 -0
  575. numpy/linalg/tests/test_deprecations.py +21 -0
  576. numpy/linalg/tests/test_linalg.py +2442 -0
  577. numpy/linalg/tests/test_regression.py +182 -0
  578. numpy/ma/API_CHANGES.txt +135 -0
  579. numpy/ma/LICENSE +24 -0
  580. numpy/ma/README.rst +236 -0
  581. numpy/ma/__init__.py +53 -0
  582. numpy/ma/__init__.pyi +458 -0
  583. numpy/ma/core.py +8929 -0
  584. numpy/ma/core.pyi +3720 -0
  585. numpy/ma/extras.py +2266 -0
  586. numpy/ma/extras.pyi +297 -0
  587. numpy/ma/mrecords.py +762 -0
  588. numpy/ma/mrecords.pyi +96 -0
  589. numpy/ma/tests/__init__.py +0 -0
  590. numpy/ma/tests/test_arrayobject.py +40 -0
  591. numpy/ma/tests/test_core.py +6008 -0
  592. numpy/ma/tests/test_deprecations.py +65 -0
  593. numpy/ma/tests/test_extras.py +1945 -0
  594. numpy/ma/tests/test_mrecords.py +495 -0
  595. numpy/ma/tests/test_old_ma.py +939 -0
  596. numpy/ma/tests/test_regression.py +83 -0
  597. numpy/ma/tests/test_subclassing.py +469 -0
  598. numpy/ma/testutils.py +294 -0
  599. numpy/ma/testutils.pyi +69 -0
  600. numpy/matlib.py +380 -0
  601. numpy/matlib.pyi +580 -0
  602. numpy/matrixlib/__init__.py +12 -0
  603. numpy/matrixlib/__init__.pyi +3 -0
  604. numpy/matrixlib/defmatrix.py +1119 -0
  605. numpy/matrixlib/defmatrix.pyi +218 -0
  606. numpy/matrixlib/tests/__init__.py +0 -0
  607. numpy/matrixlib/tests/test_defmatrix.py +455 -0
  608. numpy/matrixlib/tests/test_interaction.py +360 -0
  609. numpy/matrixlib/tests/test_masked_matrix.py +240 -0
  610. numpy/matrixlib/tests/test_matrix_linalg.py +110 -0
  611. numpy/matrixlib/tests/test_multiarray.py +17 -0
  612. numpy/matrixlib/tests/test_numeric.py +18 -0
  613. numpy/matrixlib/tests/test_regression.py +31 -0
  614. numpy/polynomial/__init__.py +187 -0
  615. numpy/polynomial/__init__.pyi +31 -0
  616. numpy/polynomial/_polybase.py +1191 -0
  617. numpy/polynomial/_polybase.pyi +262 -0
  618. numpy/polynomial/_polytypes.pyi +501 -0
  619. numpy/polynomial/chebyshev.py +2001 -0
  620. numpy/polynomial/chebyshev.pyi +180 -0
  621. numpy/polynomial/hermite.py +1738 -0
  622. numpy/polynomial/hermite.pyi +106 -0
  623. numpy/polynomial/hermite_e.py +1640 -0
  624. numpy/polynomial/hermite_e.pyi +106 -0
  625. numpy/polynomial/laguerre.py +1673 -0
  626. numpy/polynomial/laguerre.pyi +100 -0
  627. numpy/polynomial/legendre.py +1603 -0
  628. numpy/polynomial/legendre.pyi +100 -0
  629. numpy/polynomial/polynomial.py +1625 -0
  630. numpy/polynomial/polynomial.pyi +109 -0
  631. numpy/polynomial/polyutils.py +759 -0
  632. numpy/polynomial/polyutils.pyi +307 -0
  633. numpy/polynomial/tests/__init__.py +0 -0
  634. numpy/polynomial/tests/test_chebyshev.py +618 -0
  635. numpy/polynomial/tests/test_classes.py +613 -0
  636. numpy/polynomial/tests/test_hermite.py +553 -0
  637. numpy/polynomial/tests/test_hermite_e.py +554 -0
  638. numpy/polynomial/tests/test_laguerre.py +535 -0
  639. numpy/polynomial/tests/test_legendre.py +566 -0
  640. numpy/polynomial/tests/test_polynomial.py +691 -0
  641. numpy/polynomial/tests/test_polyutils.py +123 -0
  642. numpy/polynomial/tests/test_printing.py +557 -0
  643. numpy/polynomial/tests/test_symbol.py +217 -0
  644. numpy/py.typed +0 -0
  645. numpy/random/LICENSE.md +71 -0
  646. numpy/random/__init__.pxd +14 -0
  647. numpy/random/__init__.py +213 -0
  648. numpy/random/__init__.pyi +124 -0
  649. numpy/random/_bounded_integers.cpython-313t-aarch64-linux-musl.so +0 -0
  650. numpy/random/_bounded_integers.pxd +29 -0
  651. numpy/random/_bounded_integers.pyi +1 -0
  652. numpy/random/_common.cpython-313t-aarch64-linux-musl.so +0 -0
  653. numpy/random/_common.pxd +107 -0
  654. numpy/random/_common.pyi +16 -0
  655. numpy/random/_examples/cffi/extending.py +44 -0
  656. numpy/random/_examples/cffi/parse.py +53 -0
  657. numpy/random/_examples/cython/extending.pyx +77 -0
  658. numpy/random/_examples/cython/extending_distributions.pyx +117 -0
  659. numpy/random/_examples/cython/meson.build +53 -0
  660. numpy/random/_examples/numba/extending.py +86 -0
  661. numpy/random/_examples/numba/extending_distributions.py +67 -0
  662. numpy/random/_generator.cpython-313t-aarch64-linux-musl.so +0 -0
  663. numpy/random/_generator.pyi +862 -0
  664. numpy/random/_mt19937.cpython-313t-aarch64-linux-musl.so +0 -0
  665. numpy/random/_mt19937.pyi +27 -0
  666. numpy/random/_pcg64.cpython-313t-aarch64-linux-musl.so +0 -0
  667. numpy/random/_pcg64.pyi +41 -0
  668. numpy/random/_philox.cpython-313t-aarch64-linux-musl.so +0 -0
  669. numpy/random/_philox.pyi +36 -0
  670. numpy/random/_pickle.py +88 -0
  671. numpy/random/_pickle.pyi +43 -0
  672. numpy/random/_sfc64.cpython-313t-aarch64-linux-musl.so +0 -0
  673. numpy/random/_sfc64.pyi +25 -0
  674. numpy/random/bit_generator.cpython-313t-aarch64-linux-musl.so +0 -0
  675. numpy/random/bit_generator.pxd +35 -0
  676. numpy/random/bit_generator.pyi +123 -0
  677. numpy/random/c_distributions.pxd +119 -0
  678. numpy/random/lib/libnpyrandom.a +0 -0
  679. numpy/random/mtrand.cpython-313t-aarch64-linux-musl.so +0 -0
  680. numpy/random/mtrand.pyi +759 -0
  681. numpy/random/tests/__init__.py +0 -0
  682. numpy/random/tests/data/__init__.py +0 -0
  683. numpy/random/tests/data/generator_pcg64_np121.pkl.gz +0 -0
  684. numpy/random/tests/data/generator_pcg64_np126.pkl.gz +0 -0
  685. numpy/random/tests/data/mt19937-testset-1.csv +1001 -0
  686. numpy/random/tests/data/mt19937-testset-2.csv +1001 -0
  687. numpy/random/tests/data/pcg64-testset-1.csv +1001 -0
  688. numpy/random/tests/data/pcg64-testset-2.csv +1001 -0
  689. numpy/random/tests/data/pcg64dxsm-testset-1.csv +1001 -0
  690. numpy/random/tests/data/pcg64dxsm-testset-2.csv +1001 -0
  691. numpy/random/tests/data/philox-testset-1.csv +1001 -0
  692. numpy/random/tests/data/philox-testset-2.csv +1001 -0
  693. numpy/random/tests/data/sfc64-testset-1.csv +1001 -0
  694. numpy/random/tests/data/sfc64-testset-2.csv +1001 -0
  695. numpy/random/tests/data/sfc64_np126.pkl.gz +0 -0
  696. numpy/random/tests/test_direct.py +595 -0
  697. numpy/random/tests/test_extending.py +131 -0
  698. numpy/random/tests/test_generator_mt19937.py +2825 -0
  699. numpy/random/tests/test_generator_mt19937_regressions.py +221 -0
  700. numpy/random/tests/test_random.py +1724 -0
  701. numpy/random/tests/test_randomstate.py +2099 -0
  702. numpy/random/tests/test_randomstate_regression.py +213 -0
  703. numpy/random/tests/test_regression.py +175 -0
  704. numpy/random/tests/test_seed_sequence.py +79 -0
  705. numpy/random/tests/test_smoke.py +882 -0
  706. numpy/rec/__init__.py +2 -0
  707. numpy/rec/__init__.pyi +23 -0
  708. numpy/strings/__init__.py +2 -0
  709. numpy/strings/__init__.pyi +97 -0
  710. numpy/testing/__init__.py +22 -0
  711. numpy/testing/__init__.pyi +107 -0
  712. numpy/testing/_private/__init__.py +0 -0
  713. numpy/testing/_private/__init__.pyi +0 -0
  714. numpy/testing/_private/extbuild.py +250 -0
  715. numpy/testing/_private/extbuild.pyi +25 -0
  716. numpy/testing/_private/utils.py +2830 -0
  717. numpy/testing/_private/utils.pyi +505 -0
  718. numpy/testing/overrides.py +84 -0
  719. numpy/testing/overrides.pyi +10 -0
  720. numpy/testing/print_coercion_tables.py +207 -0
  721. numpy/testing/print_coercion_tables.pyi +26 -0
  722. numpy/testing/tests/__init__.py +0 -0
  723. numpy/testing/tests/test_utils.py +2123 -0
  724. numpy/tests/__init__.py +0 -0
  725. numpy/tests/test__all__.py +10 -0
  726. numpy/tests/test_configtool.py +51 -0
  727. numpy/tests/test_ctypeslib.py +383 -0
  728. numpy/tests/test_lazyloading.py +42 -0
  729. numpy/tests/test_matlib.py +59 -0
  730. numpy/tests/test_numpy_config.py +47 -0
  731. numpy/tests/test_numpy_version.py +54 -0
  732. numpy/tests/test_public_api.py +804 -0
  733. numpy/tests/test_reloading.py +76 -0
  734. numpy/tests/test_scripts.py +48 -0
  735. numpy/tests/test_warnings.py +79 -0
  736. numpy/typing/__init__.py +233 -0
  737. numpy/typing/__init__.pyi +3 -0
  738. numpy/typing/mypy_plugin.py +200 -0
  739. numpy/typing/tests/__init__.py +0 -0
  740. numpy/typing/tests/data/fail/arithmetic.pyi +126 -0
  741. numpy/typing/tests/data/fail/array_constructors.pyi +34 -0
  742. numpy/typing/tests/data/fail/array_like.pyi +15 -0
  743. numpy/typing/tests/data/fail/array_pad.pyi +6 -0
  744. numpy/typing/tests/data/fail/arrayprint.pyi +15 -0
  745. numpy/typing/tests/data/fail/arrayterator.pyi +14 -0
  746. numpy/typing/tests/data/fail/bitwise_ops.pyi +17 -0
  747. numpy/typing/tests/data/fail/char.pyi +63 -0
  748. numpy/typing/tests/data/fail/chararray.pyi +61 -0
  749. numpy/typing/tests/data/fail/comparisons.pyi +27 -0
  750. numpy/typing/tests/data/fail/constants.pyi +3 -0
  751. numpy/typing/tests/data/fail/datasource.pyi +16 -0
  752. numpy/typing/tests/data/fail/dtype.pyi +17 -0
  753. numpy/typing/tests/data/fail/einsumfunc.pyi +12 -0
  754. numpy/typing/tests/data/fail/flatiter.pyi +38 -0
  755. numpy/typing/tests/data/fail/fromnumeric.pyi +148 -0
  756. numpy/typing/tests/data/fail/histograms.pyi +12 -0
  757. numpy/typing/tests/data/fail/index_tricks.pyi +14 -0
  758. numpy/typing/tests/data/fail/lib_function_base.pyi +60 -0
  759. numpy/typing/tests/data/fail/lib_polynomial.pyi +29 -0
  760. numpy/typing/tests/data/fail/lib_utils.pyi +3 -0
  761. numpy/typing/tests/data/fail/lib_version.pyi +6 -0
  762. numpy/typing/tests/data/fail/linalg.pyi +52 -0
  763. numpy/typing/tests/data/fail/ma.pyi +155 -0
  764. numpy/typing/tests/data/fail/memmap.pyi +5 -0
  765. numpy/typing/tests/data/fail/modules.pyi +17 -0
  766. numpy/typing/tests/data/fail/multiarray.pyi +52 -0
  767. numpy/typing/tests/data/fail/ndarray.pyi +11 -0
  768. numpy/typing/tests/data/fail/ndarray_misc.pyi +49 -0
  769. numpy/typing/tests/data/fail/nditer.pyi +8 -0
  770. numpy/typing/tests/data/fail/nested_sequence.pyi +17 -0
  771. numpy/typing/tests/data/fail/npyio.pyi +24 -0
  772. numpy/typing/tests/data/fail/numerictypes.pyi +5 -0
  773. numpy/typing/tests/data/fail/random.pyi +62 -0
  774. numpy/typing/tests/data/fail/rec.pyi +17 -0
  775. numpy/typing/tests/data/fail/scalars.pyi +86 -0
  776. numpy/typing/tests/data/fail/shape.pyi +7 -0
  777. numpy/typing/tests/data/fail/shape_base.pyi +8 -0
  778. numpy/typing/tests/data/fail/stride_tricks.pyi +9 -0
  779. numpy/typing/tests/data/fail/strings.pyi +52 -0
  780. numpy/typing/tests/data/fail/testing.pyi +28 -0
  781. numpy/typing/tests/data/fail/twodim_base.pyi +39 -0
  782. numpy/typing/tests/data/fail/type_check.pyi +12 -0
  783. numpy/typing/tests/data/fail/ufunc_config.pyi +21 -0
  784. numpy/typing/tests/data/fail/ufunclike.pyi +21 -0
  785. numpy/typing/tests/data/fail/ufuncs.pyi +17 -0
  786. numpy/typing/tests/data/fail/warnings_and_errors.pyi +5 -0
  787. numpy/typing/tests/data/misc/extended_precision.pyi +9 -0
  788. numpy/typing/tests/data/mypy.ini +8 -0
  789. numpy/typing/tests/data/pass/arithmetic.py +614 -0
  790. numpy/typing/tests/data/pass/array_constructors.py +138 -0
  791. numpy/typing/tests/data/pass/array_like.py +43 -0
  792. numpy/typing/tests/data/pass/arrayprint.py +37 -0
  793. numpy/typing/tests/data/pass/arrayterator.py +28 -0
  794. numpy/typing/tests/data/pass/bitwise_ops.py +131 -0
  795. numpy/typing/tests/data/pass/comparisons.py +316 -0
  796. numpy/typing/tests/data/pass/dtype.py +57 -0
  797. numpy/typing/tests/data/pass/einsumfunc.py +36 -0
  798. numpy/typing/tests/data/pass/flatiter.py +26 -0
  799. numpy/typing/tests/data/pass/fromnumeric.py +272 -0
  800. numpy/typing/tests/data/pass/index_tricks.py +62 -0
  801. numpy/typing/tests/data/pass/lib_user_array.py +22 -0
  802. numpy/typing/tests/data/pass/lib_utils.py +19 -0
  803. numpy/typing/tests/data/pass/lib_version.py +18 -0
  804. numpy/typing/tests/data/pass/literal.py +52 -0
  805. numpy/typing/tests/data/pass/ma.py +199 -0
  806. numpy/typing/tests/data/pass/mod.py +149 -0
  807. numpy/typing/tests/data/pass/modules.py +45 -0
  808. numpy/typing/tests/data/pass/multiarray.py +77 -0
  809. numpy/typing/tests/data/pass/ndarray_conversion.py +81 -0
  810. numpy/typing/tests/data/pass/ndarray_misc.py +199 -0
  811. numpy/typing/tests/data/pass/ndarray_shape_manipulation.py +47 -0
  812. numpy/typing/tests/data/pass/nditer.py +4 -0
  813. numpy/typing/tests/data/pass/numeric.py +90 -0
  814. numpy/typing/tests/data/pass/numerictypes.py +17 -0
  815. numpy/typing/tests/data/pass/random.py +1498 -0
  816. numpy/typing/tests/data/pass/recfunctions.py +164 -0
  817. numpy/typing/tests/data/pass/scalars.py +249 -0
  818. numpy/typing/tests/data/pass/shape.py +19 -0
  819. numpy/typing/tests/data/pass/simple.py +170 -0
  820. numpy/typing/tests/data/pass/ufunc_config.py +64 -0
  821. numpy/typing/tests/data/pass/ufunclike.py +52 -0
  822. numpy/typing/tests/data/pass/ufuncs.py +16 -0
  823. numpy/typing/tests/data/pass/warnings_and_errors.py +6 -0
  824. numpy/typing/tests/data/reveal/arithmetic.pyi +719 -0
  825. numpy/typing/tests/data/reveal/array_api_info.pyi +70 -0
  826. numpy/typing/tests/data/reveal/array_constructors.pyi +277 -0
  827. numpy/typing/tests/data/reveal/arraypad.pyi +27 -0
  828. numpy/typing/tests/data/reveal/arrayprint.pyi +25 -0
  829. numpy/typing/tests/data/reveal/arraysetops.pyi +74 -0
  830. numpy/typing/tests/data/reveal/arrayterator.pyi +27 -0
  831. numpy/typing/tests/data/reveal/bitwise_ops.pyi +166 -0
  832. numpy/typing/tests/data/reveal/char.pyi +225 -0
  833. numpy/typing/tests/data/reveal/chararray.pyi +138 -0
  834. numpy/typing/tests/data/reveal/comparisons.pyi +264 -0
  835. numpy/typing/tests/data/reveal/constants.pyi +14 -0
  836. numpy/typing/tests/data/reveal/ctypeslib.pyi +81 -0
  837. numpy/typing/tests/data/reveal/datasource.pyi +23 -0
  838. numpy/typing/tests/data/reveal/dtype.pyi +132 -0
  839. numpy/typing/tests/data/reveal/einsumfunc.pyi +39 -0
  840. numpy/typing/tests/data/reveal/emath.pyi +54 -0
  841. numpy/typing/tests/data/reveal/fft.pyi +37 -0
  842. numpy/typing/tests/data/reveal/flatiter.pyi +86 -0
  843. numpy/typing/tests/data/reveal/fromnumeric.pyi +347 -0
  844. numpy/typing/tests/data/reveal/getlimits.pyi +53 -0
  845. numpy/typing/tests/data/reveal/histograms.pyi +25 -0
  846. numpy/typing/tests/data/reveal/index_tricks.pyi +70 -0
  847. numpy/typing/tests/data/reveal/lib_function_base.pyi +409 -0
  848. numpy/typing/tests/data/reveal/lib_polynomial.pyi +147 -0
  849. numpy/typing/tests/data/reveal/lib_utils.pyi +17 -0
  850. numpy/typing/tests/data/reveal/lib_version.pyi +20 -0
  851. numpy/typing/tests/data/reveal/linalg.pyi +154 -0
  852. numpy/typing/tests/data/reveal/ma.pyi +1098 -0
  853. numpy/typing/tests/data/reveal/matrix.pyi +73 -0
  854. numpy/typing/tests/data/reveal/memmap.pyi +19 -0
  855. numpy/typing/tests/data/reveal/mod.pyi +178 -0
  856. numpy/typing/tests/data/reveal/modules.pyi +51 -0
  857. numpy/typing/tests/data/reveal/multiarray.pyi +197 -0
  858. numpy/typing/tests/data/reveal/nbit_base_example.pyi +20 -0
  859. numpy/typing/tests/data/reveal/ndarray_assignability.pyi +82 -0
  860. numpy/typing/tests/data/reveal/ndarray_conversion.pyi +83 -0
  861. numpy/typing/tests/data/reveal/ndarray_misc.pyi +246 -0
  862. numpy/typing/tests/data/reveal/ndarray_shape_manipulation.pyi +47 -0
  863. numpy/typing/tests/data/reveal/nditer.pyi +49 -0
  864. numpy/typing/tests/data/reveal/nested_sequence.pyi +25 -0
  865. numpy/typing/tests/data/reveal/npyio.pyi +83 -0
  866. numpy/typing/tests/data/reveal/numeric.pyi +170 -0
  867. numpy/typing/tests/data/reveal/numerictypes.pyi +16 -0
  868. numpy/typing/tests/data/reveal/polynomial_polybase.pyi +217 -0
  869. numpy/typing/tests/data/reveal/polynomial_polyutils.pyi +218 -0
  870. numpy/typing/tests/data/reveal/polynomial_series.pyi +138 -0
  871. numpy/typing/tests/data/reveal/random.pyi +1546 -0
  872. numpy/typing/tests/data/reveal/rec.pyi +171 -0
  873. numpy/typing/tests/data/reveal/scalars.pyi +191 -0
  874. numpy/typing/tests/data/reveal/shape.pyi +13 -0
  875. numpy/typing/tests/data/reveal/shape_base.pyi +52 -0
  876. numpy/typing/tests/data/reveal/stride_tricks.pyi +27 -0
  877. numpy/typing/tests/data/reveal/strings.pyi +196 -0
  878. numpy/typing/tests/data/reveal/testing.pyi +198 -0
  879. numpy/typing/tests/data/reveal/twodim_base.pyi +225 -0
  880. numpy/typing/tests/data/reveal/type_check.pyi +67 -0
  881. numpy/typing/tests/data/reveal/ufunc_config.pyi +29 -0
  882. numpy/typing/tests/data/reveal/ufunclike.pyi +31 -0
  883. numpy/typing/tests/data/reveal/ufuncs.pyi +142 -0
  884. numpy/typing/tests/data/reveal/warnings_and_errors.pyi +11 -0
  885. numpy/typing/tests/test_isfile.py +38 -0
  886. numpy/typing/tests/test_runtime.py +110 -0
  887. numpy/typing/tests/test_typing.py +205 -0
  888. numpy/version.py +11 -0
  889. numpy/version.pyi +9 -0
  890. numpy-2.4.0.dist-info/METADATA +139 -0
  891. numpy-2.4.0.dist-info/RECORD +915 -0
  892. numpy-2.4.0.dist-info/WHEEL +5 -0
  893. numpy-2.4.0.dist-info/entry_points.txt +13 -0
  894. numpy-2.4.0.dist-info/licenses/LICENSE.txt +935 -0
  895. numpy-2.4.0.dist-info/licenses/numpy/_core/include/numpy/libdivide/LICENSE.txt +21 -0
  896. numpy-2.4.0.dist-info/licenses/numpy/_core/src/common/pythoncapi-compat/COPYING +14 -0
  897. numpy-2.4.0.dist-info/licenses/numpy/_core/src/highway/LICENSE +371 -0
  898. numpy-2.4.0.dist-info/licenses/numpy/_core/src/multiarray/dragon4_LICENSE.txt +27 -0
  899. numpy-2.4.0.dist-info/licenses/numpy/_core/src/npysort/x86-simd-sort/LICENSE.md +28 -0
  900. numpy-2.4.0.dist-info/licenses/numpy/_core/src/umath/svml/LICENSE +30 -0
  901. numpy-2.4.0.dist-info/licenses/numpy/fft/pocketfft/LICENSE.md +25 -0
  902. numpy-2.4.0.dist-info/licenses/numpy/linalg/lapack_lite/LICENSE.txt +48 -0
  903. numpy-2.4.0.dist-info/licenses/numpy/ma/LICENSE +24 -0
  904. numpy-2.4.0.dist-info/licenses/numpy/random/LICENSE.md +71 -0
  905. numpy-2.4.0.dist-info/licenses/numpy/random/src/distributions/LICENSE.md +61 -0
  906. numpy-2.4.0.dist-info/licenses/numpy/random/src/mt19937/LICENSE.md +61 -0
  907. numpy-2.4.0.dist-info/licenses/numpy/random/src/pcg64/LICENSE.md +22 -0
  908. numpy-2.4.0.dist-info/licenses/numpy/random/src/philox/LICENSE.md +31 -0
  909. numpy-2.4.0.dist-info/licenses/numpy/random/src/sfc64/LICENSE.md +27 -0
  910. numpy-2.4.0.dist-info/licenses/numpy/random/src/splitmix64/LICENSE.md +9 -0
  911. numpy.libs/libgcc_s-2d945d6c-767fb991.so.1 +0 -0
  912. numpy.libs/libgcc_s-2d945d6c.so.1 +0 -0
  913. numpy.libs/libgfortran-67378ab2-e7e7cfab.so.5.0.0 +0 -0
  914. numpy.libs/libscipy_openblas64_-1fc386ee.so +0 -0
  915. numpy.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
@@ -0,0 +1,1855 @@
1
+ import copy
2
+ import itertools
3
+ import os
4
+ import pickle
5
+ import string
6
+ import sys
7
+ import tempfile
8
+
9
+ import pytest
10
+
11
+ import numpy as np
12
+ from numpy._core.tests._natype import pd_NA
13
+ from numpy.dtypes import StringDType
14
+ from numpy.testing import IS_PYPY, assert_array_equal
15
+
16
+
17
+ def random_unicode_string_list():
18
+ """Returns an array of 10 100-character strings containing random text"""
19
+ chars = list(string.ascii_letters + string.digits)
20
+ chars = np.array(chars, dtype="U1")
21
+ ret = np.random.choice(chars, size=100 * 10, replace=True)
22
+ return ret.view("U100")
23
+
24
+
25
+ def get_dtype(na_object, coerce=True):
26
+ """Helper to work around pd_NA boolean behavior"""
27
+ # explicit is check for pd_NA because != with pd_NA returns pd_NA
28
+ if na_object is pd_NA or na_object != "unset":
29
+ return np.dtypes.StringDType(na_object=na_object, coerce=coerce)
30
+ else:
31
+ return np.dtypes.StringDType(coerce=coerce)
32
+
33
+
34
+ @pytest.fixture(params=[True, False])
35
+ def coerce(request):
36
+ """Coerce input to strings or raise an error for non-string input"""
37
+ return request.param
38
+
39
+
40
+ @pytest.fixture(
41
+ params=["unset", None, pd_NA, np.nan, float("nan"), "__nan__"],
42
+ ids=["unset", "None", "pandas.NA", "np.nan", "float('nan')", "string nan"],
43
+ )
44
+ def na_object(request):
45
+ """Possible values for the missing data sentinel"""
46
+ return request.param
47
+
48
+
49
+ @pytest.fixture()
50
+ def dtype(na_object, coerce):
51
+ """Cartesian project of missing data sentinel and string coercion options"""
52
+ return get_dtype(na_object, coerce)
53
+
54
+ @pytest.fixture
55
+ def string_list():
56
+ """Mix of short and long strings, some with unicode, some without"""
57
+ return ["abc", "def", "ghi" * 10, "A¢☃€ 😊" * 100, "Abc" * 1000, "DEF"]
58
+
59
+
60
+ @pytest.fixture(params=[True, False])
61
+ def coerce2(request):
62
+ """Second copy of the coerce fixture for tests that need two instances"""
63
+ return request.param
64
+
65
+
66
+ @pytest.fixture(
67
+ params=["unset", None, pd_NA, np.nan, float("nan"), "__nan__"],
68
+ ids=["unset", "None", "pandas.NA", "np.nan", "float('nan')", "string nan"],
69
+ )
70
+ def na_object2(request):
71
+ """Second copy of the na_object fixture for tests that need two instances"""
72
+ return request.param
73
+
74
+
75
+ @pytest.fixture()
76
+ def dtype2(na_object2, coerce2):
77
+ """Second copy of the dtype fixture for tests that need two instances"""
78
+ # explicit is check for pd_NA because != with pd_NA returns pd_NA
79
+ if na_object2 is pd_NA or na_object2 != "unset":
80
+ return StringDType(na_object=na_object2, coerce=coerce2)
81
+ else:
82
+ return StringDType(coerce=coerce2)
83
+
84
+
85
+ def test_dtype_creation():
86
+ hashes = set()
87
+ dt = StringDType()
88
+ assert not hasattr(dt, "na_object") and dt.coerce is True
89
+ hashes.add(hash(dt))
90
+
91
+ dt = StringDType(na_object=None)
92
+ assert dt.na_object is None and dt.coerce is True
93
+ hashes.add(hash(dt))
94
+
95
+ dt = StringDType(coerce=False)
96
+ assert not hasattr(dt, "na_object") and dt.coerce is False
97
+ hashes.add(hash(dt))
98
+
99
+ dt = StringDType(na_object=None, coerce=False)
100
+ assert dt.na_object is None and dt.coerce is False
101
+ hashes.add(hash(dt))
102
+
103
+ assert len(hashes) == 4
104
+
105
+ dt = np.dtype("T")
106
+ assert dt == StringDType()
107
+ assert dt.kind == "T"
108
+ assert dt.char == "T"
109
+
110
+ hashes.add(hash(dt))
111
+ assert len(hashes) == 4
112
+
113
+
114
+ def test_dtype_equality(dtype):
115
+ assert dtype == dtype
116
+ for ch in "SU":
117
+ assert dtype != np.dtype(ch)
118
+ assert dtype != np.dtype(f"{ch}8")
119
+
120
+
121
+ def test_dtype_repr(dtype):
122
+ if not hasattr(dtype, "na_object") and dtype.coerce:
123
+ assert repr(dtype) == "StringDType()"
124
+ elif dtype.coerce:
125
+ assert repr(dtype) == f"StringDType(na_object={dtype.na_object!r})"
126
+ elif not hasattr(dtype, "na_object"):
127
+ assert repr(dtype) == "StringDType(coerce=False)"
128
+ else:
129
+ assert (
130
+ repr(dtype)
131
+ == f"StringDType(na_object={dtype.na_object!r}, coerce=False)"
132
+ )
133
+
134
+
135
+ def test_create_with_na(dtype):
136
+ if not hasattr(dtype, "na_object"):
137
+ pytest.skip("does not have an na object")
138
+ na_val = dtype.na_object
139
+ string_list = ["hello", na_val, "world"]
140
+ arr = np.array(string_list, dtype=dtype)
141
+ assert str(arr) == "[" + " ".join([repr(s) for s in string_list]) + "]"
142
+ assert arr[1] is dtype.na_object
143
+
144
+
145
+ @pytest.mark.parametrize("i", list(range(5)))
146
+ def test_set_replace_na(i):
147
+ # Test strings of various lengths can be set to NaN and then replaced.
148
+ s_empty = ""
149
+ s_short = "0123456789"
150
+ s_medium = "abcdefghijklmnopqrstuvwxyz"
151
+ s_long = "-=+" * 100
152
+ strings = [s_medium, s_empty, s_short, s_medium, s_long]
153
+ a = np.array(strings, StringDType(na_object=np.nan))
154
+ for s in [a[i], s_medium + s_short, s_short, s_empty, s_long]:
155
+ a[i] = np.nan
156
+ assert np.isnan(a[i])
157
+ a[i] = s
158
+ assert a[i] == s
159
+ assert_array_equal(a, strings[:i] + [s] + strings[i + 1:])
160
+
161
+
162
+ def test_null_roundtripping():
163
+ data = ["hello\0world", "ABC\0DEF\0\0"]
164
+ arr = np.array(data, dtype="T")
165
+ assert data[0] == arr[0]
166
+ assert data[1] == arr[1]
167
+
168
+
169
+ def test_string_too_large_error():
170
+ arr = np.array(["a", "b", "c"], dtype=StringDType())
171
+ with pytest.raises(OverflowError):
172
+ arr * (sys.maxsize + 1)
173
+
174
+
175
+ @pytest.mark.parametrize(
176
+ "data",
177
+ [
178
+ ["abc", "def", "ghi"],
179
+ ["🤣", "📵", "😰"],
180
+ ["🚜", "🙃", "😾"],
181
+ ["😹", "🚠", "🚌"],
182
+ ],
183
+ )
184
+ def test_array_creation_utf8(dtype, data):
185
+ arr = np.array(data, dtype=dtype)
186
+ assert str(arr) == "[" + " ".join(["'" + str(d) + "'" for d in data]) + "]"
187
+ assert arr.dtype == dtype
188
+
189
+
190
+ @pytest.mark.parametrize(
191
+ "data",
192
+ [
193
+ [1, 2, 3],
194
+ [b"abc", b"def", b"ghi"],
195
+ [object, object, object],
196
+ ],
197
+ )
198
+ def test_scalars_string_conversion(data, dtype):
199
+ try:
200
+ str_vals = [str(d.decode('utf-8')) for d in data]
201
+ except AttributeError:
202
+ str_vals = [str(d) for d in data]
203
+ if dtype.coerce:
204
+ assert_array_equal(
205
+ np.array(data, dtype=dtype),
206
+ np.array(str_vals, dtype=dtype),
207
+ )
208
+ else:
209
+ with pytest.raises(ValueError):
210
+ np.array(data, dtype=dtype)
211
+
212
+
213
+ @pytest.mark.parametrize(
214
+ ("strings"),
215
+ [
216
+ ["this", "is", "an", "array"],
217
+ ["€", "", "😊"],
218
+ ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"],
219
+ ],
220
+ )
221
+ def test_self_casts(dtype, dtype2, strings):
222
+ if hasattr(dtype, "na_object"):
223
+ strings = strings + [dtype.na_object]
224
+ elif hasattr(dtype2, "na_object"):
225
+ strings = strings + [""]
226
+ arr = np.array(strings, dtype=dtype)
227
+ newarr = arr.astype(dtype2)
228
+
229
+ if hasattr(dtype, "na_object") and not hasattr(dtype2, "na_object"):
230
+ assert newarr[-1] == str(dtype.na_object)
231
+ with pytest.raises(TypeError):
232
+ arr.astype(dtype2, casting="safe")
233
+ elif hasattr(dtype, "na_object") and hasattr(dtype2, "na_object"):
234
+ assert newarr[-1] is dtype2.na_object
235
+ arr.astype(dtype2, casting="safe")
236
+ elif hasattr(dtype2, "na_object"):
237
+ assert newarr[-1] == ""
238
+ arr.astype(dtype2, casting="safe")
239
+ else:
240
+ arr.astype(dtype2, casting="safe")
241
+
242
+ if hasattr(dtype, "na_object") and hasattr(dtype2, "na_object"):
243
+ na1 = dtype.na_object
244
+ na2 = dtype2.na_object
245
+ if (na1 is not na2 and
246
+ # check for pd_NA first because bool(pd_NA) is an error
247
+ ((na1 is pd_NA or na2 is pd_NA) or
248
+ # the second check is a NaN check, spelled this way
249
+ # to avoid errors from math.isnan and np.isnan
250
+ (na1 != na2 and not (na1 != na1 and na2 != na2)))):
251
+ with pytest.raises(TypeError):
252
+ arr[:-1] == newarr[:-1]
253
+ return
254
+ assert_array_equal(arr[:-1], newarr[:-1])
255
+
256
+
257
+ @pytest.mark.parametrize(
258
+ ("strings"),
259
+ [
260
+ ["this", "is", "an", "array"],
261
+ ["€", "", "😊"],
262
+ ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"],
263
+ ],
264
+ )
265
+ class TestStringLikeCasts:
266
+ def test_unicode_casts(self, dtype, strings):
267
+ arr = np.array(strings, dtype=np.str_).astype(dtype)
268
+ expected = np.array(strings, dtype=dtype)
269
+ assert_array_equal(arr, expected)
270
+
271
+ arr_as_U8 = expected.astype("U8")
272
+ assert_array_equal(arr_as_U8, np.array(strings, dtype="U8"))
273
+ assert_array_equal(arr_as_U8.astype(dtype), arr)
274
+ arr_as_U3 = expected.astype("U3")
275
+ assert_array_equal(arr_as_U3, np.array(strings, dtype="U3"))
276
+ assert_array_equal(
277
+ arr_as_U3.astype(dtype),
278
+ np.array([s[:3] for s in strings], dtype=dtype),
279
+ )
280
+
281
+ def test_void_casts(self, dtype, strings):
282
+ sarr = np.array(strings, dtype=dtype)
283
+ utf8_bytes = [s.encode("utf-8") for s in strings]
284
+ void_dtype = f"V{max(len(s) for s in utf8_bytes)}"
285
+ varr = np.array(utf8_bytes, dtype=void_dtype)
286
+ assert_array_equal(varr, sarr.astype(void_dtype))
287
+ assert_array_equal(varr.astype(dtype), sarr)
288
+
289
+ def test_bytes_casts(self, dtype, strings):
290
+ sarr = np.array(strings, dtype=dtype)
291
+ try:
292
+ utf8_bytes = [s.encode("ascii") for s in strings]
293
+ bytes_dtype = f"S{max(len(s) for s in utf8_bytes)}"
294
+ barr = np.array(utf8_bytes, dtype=bytes_dtype)
295
+ assert_array_equal(barr, sarr.astype(bytes_dtype))
296
+ assert_array_equal(barr.astype(dtype), sarr)
297
+ if dtype.coerce:
298
+ barr = np.array(utf8_bytes, dtype=dtype)
299
+ assert_array_equal(barr, sarr)
300
+ barr = np.array(utf8_bytes, dtype="O")
301
+ assert_array_equal(barr.astype(dtype), sarr)
302
+ else:
303
+ with pytest.raises(ValueError):
304
+ np.array(utf8_bytes, dtype=dtype)
305
+ except UnicodeEncodeError:
306
+ with pytest.raises(UnicodeEncodeError):
307
+ sarr.astype("S20")
308
+
309
+
310
+ def test_additional_unicode_cast(dtype):
311
+ string_list = random_unicode_string_list()
312
+ arr = np.array(string_list, dtype=dtype)
313
+ # test that this short-circuits correctly
314
+ assert_array_equal(arr, arr.astype(arr.dtype))
315
+ # tests the casts via the comparison promoter
316
+ assert_array_equal(arr, arr.astype(string_list.dtype))
317
+
318
+
319
+ def test_insert_scalar(dtype, string_list):
320
+ """Test that inserting a scalar works."""
321
+ arr = np.array(string_list, dtype=dtype)
322
+ scalar_instance = "what"
323
+ arr[1] = scalar_instance
324
+ assert_array_equal(
325
+ arr,
326
+ np.array(string_list[:1] + ["what"] + string_list[2:], dtype=dtype),
327
+ )
328
+
329
+
330
+ comparison_operators = [
331
+ np.equal,
332
+ np.not_equal,
333
+ np.greater,
334
+ np.greater_equal,
335
+ np.less,
336
+ np.less_equal,
337
+ ]
338
+
339
+
340
+ @pytest.mark.parametrize("op", comparison_operators)
341
+ @pytest.mark.parametrize("o_dtype", [np.str_, object, StringDType()])
342
+ def test_comparisons(string_list, dtype, op, o_dtype):
343
+ sarr = np.array(string_list, dtype=dtype)
344
+ oarr = np.array(string_list, dtype=o_dtype)
345
+
346
+ # test that comparison operators work
347
+ res = op(sarr, sarr)
348
+ ores = op(oarr, oarr)
349
+ # test that promotion works as well
350
+ orres = op(sarr, oarr)
351
+ olres = op(oarr, sarr)
352
+
353
+ assert_array_equal(res, ores)
354
+ assert_array_equal(res, orres)
355
+ assert_array_equal(res, olres)
356
+
357
+ # test we get the correct answer for unequal length strings
358
+ sarr2 = np.array([s + "2" for s in string_list], dtype=dtype)
359
+ oarr2 = np.array([s + "2" for s in string_list], dtype=o_dtype)
360
+
361
+ res = op(sarr, sarr2)
362
+ ores = op(oarr, oarr2)
363
+ olres = op(oarr, sarr2)
364
+ orres = op(sarr, oarr2)
365
+
366
+ assert_array_equal(res, ores)
367
+ assert_array_equal(res, olres)
368
+ assert_array_equal(res, orres)
369
+
370
+ res = op(sarr2, sarr)
371
+ ores = op(oarr2, oarr)
372
+ olres = op(oarr2, sarr)
373
+ orres = op(sarr2, oarr)
374
+
375
+ assert_array_equal(res, ores)
376
+ assert_array_equal(res, olres)
377
+ assert_array_equal(res, orres)
378
+
379
+
380
+ def test_isnan(dtype, string_list):
381
+ if not hasattr(dtype, "na_object"):
382
+ pytest.skip("no na support")
383
+ sarr = np.array(string_list + [dtype.na_object], dtype=dtype)
384
+ is_nan = isinstance(dtype.na_object, float) and np.isnan(dtype.na_object)
385
+ bool_errors = 0
386
+ try:
387
+ bool(dtype.na_object)
388
+ except TypeError:
389
+ bool_errors = 1
390
+ if is_nan or bool_errors:
391
+ # isnan is only true when na_object is a NaN
392
+ assert_array_equal(
393
+ np.isnan(sarr),
394
+ np.array([0] * len(string_list) + [1], dtype=np.bool),
395
+ )
396
+ else:
397
+ assert not np.any(np.isnan(sarr))
398
+
399
+
400
+ def test_pickle(dtype, string_list):
401
+ arr = np.array(string_list, dtype=dtype)
402
+
403
+ with tempfile.NamedTemporaryFile("wb", delete=False) as f:
404
+ pickle.dump([arr, dtype], f)
405
+
406
+ with open(f.name, "rb") as f:
407
+ res = pickle.load(f)
408
+
409
+ assert_array_equal(res[0], arr)
410
+ assert res[1] == dtype
411
+
412
+ os.remove(f.name)
413
+
414
+
415
+ def test_stdlib_copy(dtype, string_list):
416
+ arr = np.array(string_list, dtype=dtype)
417
+
418
+ assert_array_equal(copy.copy(arr), arr)
419
+ assert_array_equal(copy.deepcopy(arr), arr)
420
+
421
+
422
+ @pytest.mark.parametrize(
423
+ "strings",
424
+ [
425
+ ["left", "right", "leftovers", "righty", "up", "down"],
426
+ [
427
+ "left" * 10,
428
+ "right" * 10,
429
+ "leftovers" * 10,
430
+ "righty" * 10,
431
+ "up" * 10,
432
+ ],
433
+ ["🤣🤣", "🤣", "📵", "😰"],
434
+ ["🚜", "🙃", "😾"],
435
+ ["😹", "🚠", "🚌"],
436
+ ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"],
437
+ ],
438
+ )
439
+ def test_sort(dtype, strings):
440
+ """Test that sorting matches python's internal sorting."""
441
+
442
+ def test_sort(strings, arr_sorted):
443
+ arr = np.array(strings, dtype=dtype)
444
+ na_object = getattr(arr.dtype, "na_object", "")
445
+ if na_object is None and None in strings:
446
+ with pytest.raises(
447
+ ValueError,
448
+ match="Cannot compare null that is not a nan-like value",
449
+ ):
450
+ np.argsort(arr)
451
+ argsorted = None
452
+ elif na_object is pd_NA or na_object != '':
453
+ argsorted = None
454
+ else:
455
+ argsorted = np.argsort(arr)
456
+ np.random.default_rng().shuffle(arr)
457
+ if na_object is None and None in strings:
458
+ with pytest.raises(
459
+ ValueError,
460
+ match="Cannot compare null that is not a nan-like value",
461
+ ):
462
+ arr.sort()
463
+ else:
464
+ arr.sort()
465
+ assert np.array_equal(arr, arr_sorted, equal_nan=True)
466
+ if argsorted is not None:
467
+ assert np.array_equal(argsorted, np.argsort(strings))
468
+
469
+ # make a copy so we don't mutate the lists in the fixture
470
+ strings = strings.copy()
471
+ arr_sorted = np.array(sorted(strings), dtype=dtype)
472
+ test_sort(strings, arr_sorted)
473
+
474
+ if not hasattr(dtype, "na_object"):
475
+ return
476
+
477
+ # make sure NAs get sorted to the end of the array and string NAs get
478
+ # sorted like normal strings
479
+ strings.insert(0, dtype.na_object)
480
+ strings.insert(2, dtype.na_object)
481
+ # can't use append because doing that with NA converts
482
+ # the result to object dtype
483
+ if not isinstance(dtype.na_object, str):
484
+ arr_sorted = np.array(
485
+ arr_sorted.tolist() + [dtype.na_object, dtype.na_object],
486
+ dtype=dtype,
487
+ )
488
+ else:
489
+ arr_sorted = np.array(sorted(strings), dtype=dtype)
490
+
491
+ test_sort(strings, arr_sorted)
492
+
493
+
494
+ @pytest.mark.parametrize(
495
+ "strings",
496
+ [
497
+ ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"],
498
+ ["A¢☃€ 😊", "", " ", " "],
499
+ ["", "a", "😸", "ááðfáíóåéë"],
500
+ ],
501
+ )
502
+ def test_nonzero(strings, na_object):
503
+ dtype = get_dtype(na_object)
504
+ arr = np.array(strings, dtype=dtype)
505
+ is_nonzero = np.array(
506
+ [i for i, item in enumerate(strings) if len(item) != 0])
507
+ assert_array_equal(arr.nonzero()[0], is_nonzero)
508
+
509
+ if na_object is not pd_NA and na_object == 'unset':
510
+ return
511
+
512
+ strings_with_na = np.array(strings + [na_object], dtype=dtype)
513
+ is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0]
514
+
515
+ if is_nan:
516
+ assert strings_with_na.nonzero()[0][-1] == 4
517
+ else:
518
+ assert strings_with_na.nonzero()[0][-1] == 3
519
+
520
+ # check that the casting to bool and nonzero give consistent results
521
+ assert_array_equal(strings_with_na[strings_with_na.nonzero()],
522
+ strings_with_na[strings_with_na.astype(bool)])
523
+
524
+
525
+ def test_where(string_list, na_object):
526
+ dtype = get_dtype(na_object)
527
+ a = np.array(string_list, dtype=dtype)
528
+ b = a[::-1]
529
+ res = np.where([True, False, True, False, True, False], a, b)
530
+ assert_array_equal(res, [a[0], b[1], a[2], b[3], a[4], b[5]])
531
+
532
+
533
+ def test_fancy_indexing(string_list):
534
+ sarr = np.array(string_list, dtype="T")
535
+ assert_array_equal(sarr, sarr[np.arange(sarr.shape[0])])
536
+
537
+ inds = [
538
+ [True, True],
539
+ [0, 1],
540
+ ...,
541
+ np.array([0, 1], dtype='uint8'),
542
+ ]
543
+
544
+ lops = [
545
+ ['a' * 25, 'b' * 25],
546
+ ['', ''],
547
+ ['hello', 'world'],
548
+ ['hello', 'world' * 25],
549
+ ]
550
+
551
+ # see gh-27003 and gh-27053
552
+ for ind in inds:
553
+ for lop in lops:
554
+ a = np.array(lop, dtype="T")
555
+ assert_array_equal(a[ind], a)
556
+ rop = ['d' * 25, 'e' * 25]
557
+ for b in [rop, np.array(rop, dtype="T")]:
558
+ a[ind] = b
559
+ assert_array_equal(a, b)
560
+ assert a[0] == 'd' * 25
561
+
562
+ # see gh-29279
563
+ data = [
564
+ ["AAAAAAAAAAAAAAAAA"],
565
+ ["BBBBBBBBBBBBBBBBBBBBBBBBBBBBB"],
566
+ ["CCCCCCCCCCCCCCCCC"],
567
+ ["DDDDDDDDDDDDDDDDD"],
568
+ ]
569
+ sarr = np.array(data, dtype=np.dtypes.StringDType())
570
+ uarr = np.array(data, dtype="U30")
571
+ for ind in [[0], [1], [2], [3], [[0, 0]], [[1, 1, 3]], [[1, 1]]]:
572
+ assert_array_equal(sarr[ind], uarr[ind])
573
+
574
+
575
+ def test_flatiter_indexing():
576
+ # see gh-29659
577
+ arr = np.array(['hello', 'world'], dtype='T')
578
+ arr.flat[:] = 9223372036854775
579
+ assert_array_equal(arr, np.array([9223372036854775] * 2, dtype='T'))
580
+
581
+
582
+ def test_creation_functions():
583
+ assert_array_equal(np.zeros(3, dtype="T"), ["", "", ""])
584
+ assert_array_equal(np.empty(3, dtype="T"), ["", "", ""])
585
+
586
+ assert np.zeros(3, dtype="T")[0] == ""
587
+ assert np.empty(3, dtype="T")[0] == ""
588
+
589
+
590
+ def test_concatenate(string_list):
591
+ sarr = np.array(string_list, dtype="T")
592
+ sarr_cat = np.array(string_list + string_list, dtype="T")
593
+
594
+ assert_array_equal(np.concatenate([sarr], axis=0), sarr)
595
+
596
+
597
+ def test_resize_method(string_list):
598
+ sarr = np.array(string_list, dtype="T")
599
+ if IS_PYPY:
600
+ sarr.resize(len(string_list) + 3, refcheck=False)
601
+ else:
602
+ sarr.resize(len(string_list) + 3)
603
+ assert_array_equal(sarr, np.array(string_list + [''] * 3, dtype="T"))
604
+
605
+
606
+ def test_create_with_copy_none(string_list):
607
+ arr = np.array(string_list, dtype=StringDType())
608
+ # create another stringdtype array with an arena that has a different
609
+ # in-memory layout than the first array
610
+ arr_rev = np.array(string_list[::-1], dtype=StringDType())
611
+
612
+ # this should create a copy and the resulting array
613
+ # shouldn't share an allocator or arena with arr_rev, despite
614
+ # explicitly passing arr_rev.dtype
615
+ arr_copy = np.array(arr, copy=None, dtype=arr_rev.dtype)
616
+ np.testing.assert_array_equal(arr, arr_copy)
617
+ assert arr_copy.base is None
618
+
619
+ with pytest.raises(ValueError, match="Unable to avoid copy"):
620
+ np.array(arr, copy=False, dtype=arr_rev.dtype)
621
+
622
+ # because we're using arr's dtype instance, the view is safe
623
+ arr_view = np.array(arr, copy=None, dtype=arr.dtype)
624
+ np.testing.assert_array_equal(arr, arr)
625
+ np.testing.assert_array_equal(arr_view[::-1], arr_rev)
626
+ assert arr_view is arr
627
+
628
+
629
+ def test_astype_copy_false():
630
+ orig_dt = StringDType()
631
+ arr = np.array(["hello", "world"], dtype=StringDType())
632
+ assert not arr.astype(StringDType(coerce=False), copy=False).dtype.coerce
633
+
634
+ assert arr.astype(orig_dt, copy=False).dtype is orig_dt
635
+
636
+ @pytest.mark.parametrize(
637
+ "strings",
638
+ [
639
+ ["left", "right", "leftovers", "righty", "up", "down"],
640
+ ["🤣🤣", "🤣", "📵", "😰"],
641
+ ["🚜", "🙃", "😾"],
642
+ ["😹", "🚠", "🚌"],
643
+ ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"],
644
+ ],
645
+ )
646
+ def test_argmax(strings):
647
+ """Test that argmax/argmin matches what python calculates."""
648
+ arr = np.array(strings, dtype="T")
649
+ assert np.argmax(arr) == strings.index(max(strings))
650
+ assert np.argmin(arr) == strings.index(min(strings))
651
+
652
+
653
+ @pytest.mark.parametrize(
654
+ "arrfunc,expected",
655
+ [
656
+ [np.sort, None],
657
+ [np.nonzero, (np.array([], dtype=np.int_),)],
658
+ [np.argmax, 0],
659
+ [np.argmin, 0],
660
+ ],
661
+ )
662
+ def test_arrfuncs_zeros(arrfunc, expected):
663
+ arr = np.zeros(10, dtype="T")
664
+ result = arrfunc(arr)
665
+ if expected is None:
666
+ expected = arr
667
+ assert_array_equal(result, expected, strict=True)
668
+
669
+
670
+ @pytest.mark.parametrize(
671
+ ("strings", "cast_answer", "any_answer", "all_answer"),
672
+ [
673
+ [["hello", "world"], [True, True], True, True],
674
+ [["", ""], [False, False], False, False],
675
+ [["hello", ""], [True, False], True, False],
676
+ [["", "world"], [False, True], True, False],
677
+ ],
678
+ )
679
+ def test_cast_to_bool(strings, cast_answer, any_answer, all_answer):
680
+ sarr = np.array(strings, dtype="T")
681
+ assert_array_equal(sarr.astype("bool"), cast_answer)
682
+
683
+ assert np.any(sarr) == any_answer
684
+ assert np.all(sarr) == all_answer
685
+
686
+
687
+ @pytest.mark.parametrize(
688
+ ("strings", "cast_answer"),
689
+ [
690
+ [[True, True], ["True", "True"]],
691
+ [[False, False], ["False", "False"]],
692
+ [[True, False], ["True", "False"]],
693
+ [[False, True], ["False", "True"]],
694
+ ],
695
+ )
696
+ def test_cast_from_bool(strings, cast_answer):
697
+ barr = np.array(strings, dtype=bool)
698
+ assert_array_equal(barr.astype("T"), np.array(cast_answer, dtype="T"))
699
+
700
+
701
+ @pytest.mark.parametrize("bitsize", [8, 16, 32, 64])
702
+ @pytest.mark.parametrize("signed", [True, False])
703
+ def test_sized_integer_casts(bitsize, signed):
704
+ idtype = f"int{bitsize}"
705
+ if signed:
706
+ inp = [-(2**p - 1) for p in reversed(range(bitsize - 1))]
707
+ inp += [2**p - 1 for p in range(1, bitsize - 1)]
708
+ else:
709
+ idtype = "u" + idtype
710
+ inp = [2**p - 1 for p in range(bitsize)]
711
+ ainp = np.array(inp, dtype=idtype)
712
+ assert_array_equal(ainp, ainp.astype("T").astype(idtype))
713
+
714
+ # safe casting works
715
+ ainp.astype("T", casting="safe")
716
+
717
+ with pytest.raises(TypeError):
718
+ ainp.astype("T").astype(idtype, casting="safe")
719
+
720
+ oob = [str(2**bitsize), str(-(2**bitsize))]
721
+ with pytest.raises(OverflowError):
722
+ np.array(oob, dtype="T").astype(idtype)
723
+
724
+ with pytest.raises(ValueError):
725
+ np.array(["1", np.nan, "3"],
726
+ dtype=StringDType(na_object=np.nan)).astype(idtype)
727
+
728
+
729
+ @pytest.mark.parametrize("typename", ["byte", "short", "int", "longlong"])
730
+ @pytest.mark.parametrize("signed", ["", "u"])
731
+ def test_unsized_integer_casts(typename, signed):
732
+ idtype = f"{signed}{typename}"
733
+
734
+ inp = [1, 2, 3, 4]
735
+ ainp = np.array(inp, dtype=idtype)
736
+ assert_array_equal(ainp, ainp.astype("T").astype(idtype))
737
+
738
+
739
+ @pytest.mark.parametrize(
740
+ "typename",
741
+ [
742
+ pytest.param(
743
+ "longdouble",
744
+ marks=pytest.mark.xfail(
745
+ np.dtypes.LongDoubleDType() != np.dtypes.Float64DType(),
746
+ reason="numpy lacks an ld2a implementation",
747
+ strict=True,
748
+ ),
749
+ ),
750
+ "float64",
751
+ "float32",
752
+ "float16",
753
+ ],
754
+ )
755
+ def test_float_casts(typename):
756
+ inp = [1.1, 2.8, -3.2, 2.7e4]
757
+ ainp = np.array(inp, dtype=typename)
758
+ assert_array_equal(ainp, ainp.astype("T").astype(typename))
759
+
760
+ inp = [0.1]
761
+ sres = np.array(inp, dtype=typename).astype("T")
762
+ res = sres.astype(typename)
763
+ assert_array_equal(np.array(inp, dtype=typename), res)
764
+ assert sres[0] == "0.1"
765
+
766
+ if typename == "longdouble":
767
+ # let's not worry about platform-dependent rounding of longdouble
768
+ return
769
+
770
+ fi = np.finfo(typename)
771
+
772
+ inp = [1e-324, fi.smallest_subnormal, -1e-324, -fi.smallest_subnormal]
773
+ eres = [0, fi.smallest_subnormal, -0, -fi.smallest_subnormal]
774
+ res = np.array(inp, dtype=typename).astype("T").astype(typename)
775
+ assert_array_equal(eres, res)
776
+
777
+ inp = [2e308, fi.max, -2e308, fi.min]
778
+ eres = [np.inf, fi.max, -np.inf, fi.min]
779
+ res = np.array(inp, dtype=typename).astype("T").astype(typename)
780
+ assert_array_equal(eres, res)
781
+
782
+
783
+ def test_float_nan_cast_na_object():
784
+ # gh-28157
785
+ dt = np.dtypes.StringDType(na_object=np.nan)
786
+ arr1 = np.full((1,), fill_value=np.nan, dtype=dt)
787
+ arr2 = np.full_like(arr1, fill_value=np.nan)
788
+
789
+ assert arr1.item() is np.nan
790
+ assert arr2.item() is np.nan
791
+
792
+ inp = [1.2, 2.3, np.nan]
793
+ arr = np.array(inp).astype(dt)
794
+ assert arr[2] is np.nan
795
+ assert arr[0] == '1.2'
796
+
797
+
798
+ @pytest.mark.parametrize(
799
+ "typename",
800
+ [
801
+ "csingle",
802
+ "cdouble",
803
+ pytest.param(
804
+ "clongdouble",
805
+ marks=pytest.mark.xfail(
806
+ np.dtypes.CLongDoubleDType() != np.dtypes.Complex128DType(),
807
+ reason="numpy lacks an ld2a implementation",
808
+ strict=True,
809
+ ),
810
+ ),
811
+ ],
812
+ )
813
+ def test_cfloat_casts(typename):
814
+ inp = [1.1 + 1.1j, 2.8 + 2.8j, -3.2 - 3.2j, 2.7e4 + 2.7e4j]
815
+ ainp = np.array(inp, dtype=typename)
816
+ assert_array_equal(ainp, ainp.astype("T").astype(typename))
817
+
818
+ inp = [0.1 + 0.1j]
819
+ sres = np.array(inp, dtype=typename).astype("T")
820
+ res = sres.astype(typename)
821
+ assert_array_equal(np.array(inp, dtype=typename), res)
822
+ assert sres[0] == "(0.1+0.1j)"
823
+
824
+
825
+ def test_take(string_list):
826
+ sarr = np.array(string_list, dtype="T")
827
+ res = sarr.take(np.arange(len(string_list)))
828
+ assert_array_equal(sarr, res)
829
+
830
+ # make sure it also works for out
831
+ out = np.empty(len(string_list), dtype="T")
832
+ out[0] = "hello"
833
+ res = sarr.take(np.arange(len(string_list)), out=out)
834
+ assert res is out
835
+ assert_array_equal(sarr, res)
836
+
837
+
838
+ @pytest.mark.parametrize("use_out", [True, False])
839
+ @pytest.mark.parametrize(
840
+ "ufunc_name,func",
841
+ [
842
+ ("min", min),
843
+ ("max", max),
844
+ ],
845
+ )
846
+ def test_ufuncs_minmax(string_list, ufunc_name, func, use_out):
847
+ """Test that the min/max ufuncs match Python builtin min/max behavior."""
848
+ arr = np.array(string_list, dtype="T")
849
+ uarr = np.array(string_list, dtype=str)
850
+ res = np.array(func(string_list), dtype="T")
851
+ assert_array_equal(getattr(arr, ufunc_name)(), res)
852
+
853
+ ufunc = getattr(np, ufunc_name + "imum")
854
+
855
+ if use_out:
856
+ res = ufunc(arr, arr, out=arr)
857
+ else:
858
+ res = ufunc(arr, arr)
859
+
860
+ assert_array_equal(uarr, res)
861
+ assert_array_equal(getattr(arr, ufunc_name)(), func(string_list))
862
+
863
+
864
+ def test_max_regression():
865
+ arr = np.array(['y', 'y', 'z'], dtype="T")
866
+ assert arr.max() == 'z'
867
+
868
+
869
+ @pytest.mark.parametrize("use_out", [True, False])
870
+ @pytest.mark.parametrize(
871
+ "other_strings",
872
+ [
873
+ ["abc", "def" * 500, "ghi" * 16, "🤣" * 100, "📵", "😰"],
874
+ ["🚜", "🙃", "😾", "😹", "🚠", "🚌"],
875
+ ["🥦", "¨", "⨯", "∰ ", "⨌ ", "⎶ "],
876
+ ],
877
+ )
878
+ def test_ufunc_add(dtype, string_list, other_strings, use_out):
879
+ arr1 = np.array(string_list, dtype=dtype)
880
+ arr2 = np.array(other_strings, dtype=dtype)
881
+ result = np.array([a + b for a, b in zip(arr1, arr2)], dtype=dtype)
882
+
883
+ if use_out:
884
+ res = np.add(arr1, arr2, out=arr1)
885
+ else:
886
+ res = np.add(arr1, arr2)
887
+
888
+ assert_array_equal(res, result)
889
+
890
+ if not hasattr(dtype, "na_object"):
891
+ return
892
+
893
+ is_nan = isinstance(dtype.na_object, float) and np.isnan(dtype.na_object)
894
+ is_str = isinstance(dtype.na_object, str)
895
+ bool_errors = 0
896
+ try:
897
+ bool(dtype.na_object)
898
+ except TypeError:
899
+ bool_errors = 1
900
+
901
+ arr1 = np.array([dtype.na_object] + string_list, dtype=dtype)
902
+ arr2 = np.array(other_strings + [dtype.na_object], dtype=dtype)
903
+
904
+ if is_nan or bool_errors or is_str:
905
+ res = np.add(arr1, arr2)
906
+ assert_array_equal(res[1:-1], arr1[1:-1] + arr2[1:-1])
907
+ if not is_str:
908
+ assert res[0] is dtype.na_object and res[-1] is dtype.na_object
909
+ else:
910
+ assert res[0] == dtype.na_object + arr2[0]
911
+ assert res[-1] == arr1[-1] + dtype.na_object
912
+ else:
913
+ with pytest.raises(ValueError):
914
+ np.add(arr1, arr2)
915
+
916
+
917
+ def test_ufunc_add_reduce(dtype):
918
+ values = ["a", "this is a long string", "c"]
919
+ arr = np.array(values, dtype=dtype)
920
+ out = np.empty((), dtype=dtype)
921
+
922
+ expected = np.array("".join(values), dtype=dtype)
923
+ assert_array_equal(np.add.reduce(arr), expected)
924
+
925
+ np.add.reduce(arr, out=out)
926
+ assert_array_equal(out, expected)
927
+
928
+
929
+ def test_add_promoter(string_list):
930
+ arr = np.array(string_list, dtype=StringDType())
931
+ lresult = np.array(["hello" + s for s in string_list], dtype=StringDType())
932
+ rresult = np.array([s + "hello" for s in string_list], dtype=StringDType())
933
+
934
+ for op in ["hello", np.str_("hello"), np.array(["hello"])]:
935
+ assert_array_equal(op + arr, lresult)
936
+ assert_array_equal(arr + op, rresult)
937
+
938
+ # The promoter should be able to handle things if users pass `dtype=`
939
+ res = np.add("hello", string_list, dtype=StringDType)
940
+ assert res.dtype == StringDType()
941
+
942
+ # The promoter should not kick in if users override the input,
943
+ # which means arr is cast, this fails because of the unknown length.
944
+ with pytest.raises(TypeError, match="cannot cast dtype"):
945
+ np.add(arr, "add", signature=("U", "U", None), casting="unsafe")
946
+
947
+ # But it must simply reject the following:
948
+ with pytest.raises(TypeError, match=".*did not contain a loop"):
949
+ np.add(arr, "add", signature=(None, "U", None))
950
+
951
+ with pytest.raises(TypeError, match=".*did not contain a loop"):
952
+ np.add("a", "b", signature=("U", "U", StringDType))
953
+
954
+
955
+ def test_add_no_legacy_promote_with_signature():
956
+ # Possibly misplaced, but useful to test with string DType. We check that
957
+ # if there is clearly no loop found, a stray `dtype=` doesn't break things
958
+ # Regression test for the bad error in gh-26735
959
+ # (If legacy promotion is gone, this can be deleted...)
960
+ with pytest.raises(TypeError, match=".*did not contain a loop"):
961
+ np.add("3", 6, dtype=StringDType)
962
+
963
+
964
+ def test_add_promoter_reduce():
965
+ # Exact TypeError could change, but ensure StringDtype doesn't match
966
+ with pytest.raises(TypeError, match="the resolved dtypes are not"):
967
+ np.add.reduce(np.array(["a", "b"], dtype="U"))
968
+
969
+ # On the other hand, using `dtype=T` in the *ufunc* should work.
970
+ np.add.reduce(np.array(["a", "b"], dtype="U"), dtype=np.dtypes.StringDType)
971
+
972
+
973
+ def test_multiply_reduce():
974
+ # At the time of writing (NumPy 2.0) this is very limited (and rather
975
+ # ridiculous anyway). But it works and actually makes some sense...
976
+ # (NumPy does not allow non-scalar initial values)
977
+ repeats = np.array([2, 3, 4])
978
+ val = "school-🚌"
979
+ res = np.multiply.reduce(repeats, initial=val, dtype=np.dtypes.StringDType)
980
+ assert res == val * np.prod(repeats)
981
+
982
+
983
+ def test_multiply_two_string_raises():
984
+ arr = np.array(["hello", "world"], dtype="T")
985
+ with pytest.raises(np._core._exceptions._UFuncNoLoopError):
986
+ np.multiply(arr, arr)
987
+
988
+
989
+ @pytest.mark.parametrize("use_out", [True, False])
990
+ @pytest.mark.parametrize("other", [2, [2, 1, 3, 4, 1, 3]])
991
+ @pytest.mark.parametrize(
992
+ "other_dtype",
993
+ [
994
+ None,
995
+ "int8",
996
+ "int16",
997
+ "int32",
998
+ "int64",
999
+ "uint8",
1000
+ "uint16",
1001
+ "uint32",
1002
+ "uint64",
1003
+ "short",
1004
+ "int",
1005
+ "intp",
1006
+ "long",
1007
+ "longlong",
1008
+ "ushort",
1009
+ "uint",
1010
+ "uintp",
1011
+ "ulong",
1012
+ "ulonglong",
1013
+ ],
1014
+ )
1015
+ def test_ufunc_multiply(dtype, string_list, other, other_dtype, use_out):
1016
+ """Test the two-argument ufuncs match python builtin behavior."""
1017
+ arr = np.array(string_list, dtype=dtype)
1018
+ if other_dtype is not None:
1019
+ other_dtype = np.dtype(other_dtype)
1020
+ try:
1021
+ len(other)
1022
+ result = [s * o for s, o in zip(string_list, other)]
1023
+ other = np.array(other)
1024
+ if other_dtype is not None:
1025
+ other = other.astype(other_dtype)
1026
+ except TypeError:
1027
+ if other_dtype is not None:
1028
+ other = other_dtype.type(other)
1029
+ result = [s * other for s in string_list]
1030
+
1031
+ if use_out:
1032
+ arr_cache = arr.copy()
1033
+ lres = np.multiply(arr, other, out=arr)
1034
+ assert_array_equal(lres, result)
1035
+ arr[:] = arr_cache
1036
+ assert lres is arr
1037
+ arr *= other
1038
+ assert_array_equal(arr, result)
1039
+ arr[:] = arr_cache
1040
+ rres = np.multiply(other, arr, out=arr)
1041
+ assert rres is arr
1042
+ assert_array_equal(rres, result)
1043
+ else:
1044
+ lres = arr * other
1045
+ assert_array_equal(lres, result)
1046
+ rres = other * arr
1047
+ assert_array_equal(rres, result)
1048
+
1049
+ if not hasattr(dtype, "na_object"):
1050
+ return
1051
+
1052
+ is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0]
1053
+ is_str = isinstance(dtype.na_object, str)
1054
+ bool_errors = 0
1055
+ try:
1056
+ bool(dtype.na_object)
1057
+ except TypeError:
1058
+ bool_errors = 1
1059
+
1060
+ arr = np.array(string_list + [dtype.na_object], dtype=dtype)
1061
+
1062
+ try:
1063
+ len(other)
1064
+ other = np.append(other, 3)
1065
+ if other_dtype is not None:
1066
+ other = other.astype(other_dtype)
1067
+ except TypeError:
1068
+ pass
1069
+
1070
+ if is_nan or bool_errors or is_str:
1071
+ for res in [arr * other, other * arr]:
1072
+ assert_array_equal(res[:-1], result)
1073
+ if not is_str:
1074
+ assert res[-1] is dtype.na_object
1075
+ else:
1076
+ try:
1077
+ assert res[-1] == dtype.na_object * other[-1]
1078
+ except (IndexError, TypeError):
1079
+ assert res[-1] == dtype.na_object * other
1080
+ else:
1081
+ with pytest.raises(TypeError):
1082
+ arr * other
1083
+ with pytest.raises(TypeError):
1084
+ other * arr
1085
+
1086
+
1087
+ def test_findlike_promoters():
1088
+ r = "Wally"
1089
+ l = "Where's Wally?"
1090
+ s = np.int32(3)
1091
+ e = np.int8(13)
1092
+ for dtypes in [("T", "U"), ("U", "T")]:
1093
+ for function, answer in [
1094
+ (np.strings.index, 8),
1095
+ (np.strings.endswith, True),
1096
+ ]:
1097
+ assert answer == function(
1098
+ np.array(l, dtype=dtypes[0]), np.array(r, dtype=dtypes[1]), s, e
1099
+ )
1100
+
1101
+
1102
+ def test_strip_promoter():
1103
+ arg = ["Hello!!!!", "Hello??!!"]
1104
+ strip_char = "!"
1105
+ answer = ["Hello", "Hello??"]
1106
+ for dtypes in [("T", "U"), ("U", "T")]:
1107
+ result = np.strings.strip(
1108
+ np.array(arg, dtype=dtypes[0]),
1109
+ np.array(strip_char, dtype=dtypes[1])
1110
+ )
1111
+ assert_array_equal(result, answer)
1112
+ assert result.dtype.char == "T"
1113
+
1114
+
1115
+ def test_replace_promoter():
1116
+ arg = ["Hello, planet!", "planet, Hello!"]
1117
+ old = "planet"
1118
+ new = "world"
1119
+ answer = ["Hello, world!", "world, Hello!"]
1120
+ for dtypes in itertools.product("TU", repeat=3):
1121
+ if dtypes == ("U", "U", "U"):
1122
+ continue
1123
+ answer_arr = np.strings.replace(
1124
+ np.array(arg, dtype=dtypes[0]),
1125
+ np.array(old, dtype=dtypes[1]),
1126
+ np.array(new, dtype=dtypes[2]),
1127
+ )
1128
+ assert_array_equal(answer_arr, answer)
1129
+ assert answer_arr.dtype.char == "T"
1130
+
1131
+
1132
+ def test_center_promoter():
1133
+ arg = ["Hello", "planet!"]
1134
+ fillchar = "/"
1135
+ for dtypes in [("T", "U"), ("U", "T")]:
1136
+ answer = np.strings.center(
1137
+ np.array(arg, dtype=dtypes[0]), 9, np.array(fillchar, dtype=dtypes[1])
1138
+ )
1139
+ assert_array_equal(answer, ["//Hello//", "/planet!/"])
1140
+ assert answer.dtype.char == "T"
1141
+
1142
+
1143
+ DATETIME_INPUT = [
1144
+ np.datetime64("1923-04-14T12:43:12"),
1145
+ np.datetime64("1994-06-21T14:43:15"),
1146
+ np.datetime64("2001-10-15T04:10:32"),
1147
+ np.datetime64("NaT"),
1148
+ np.datetime64("1995-11-25T16:02:16"),
1149
+ np.datetime64("2005-01-04T03:14:12"),
1150
+ np.datetime64("2041-12-03T14:05:03"),
1151
+ ]
1152
+
1153
+
1154
+ TIMEDELTA_INPUT = [
1155
+ np.timedelta64(12358, "s"),
1156
+ np.timedelta64(23, "s"),
1157
+ np.timedelta64(74, "s"),
1158
+ np.timedelta64("NaT"),
1159
+ np.timedelta64(23, "s"),
1160
+ np.timedelta64(73, "s"),
1161
+ np.timedelta64(7, "s"),
1162
+ ]
1163
+
1164
+
1165
+ @pytest.mark.parametrize(
1166
+ "input_data, input_dtype",
1167
+ [
1168
+ (DATETIME_INPUT, "M8[s]"),
1169
+ (TIMEDELTA_INPUT, "m8[s]")
1170
+ ]
1171
+ )
1172
+ def test_datetime_timedelta_cast(dtype, input_data, input_dtype):
1173
+
1174
+ a = np.array(input_data, dtype=input_dtype)
1175
+
1176
+ has_na = hasattr(dtype, "na_object")
1177
+ is_str = isinstance(getattr(dtype, "na_object", None), str)
1178
+
1179
+ if not has_na or is_str:
1180
+ a = np.delete(a, 3)
1181
+
1182
+ sa = a.astype(dtype)
1183
+ ra = sa.astype(a.dtype)
1184
+
1185
+ if has_na and not is_str:
1186
+ assert sa[3] is dtype.na_object
1187
+ assert np.isnat(ra[3])
1188
+
1189
+ assert_array_equal(a, ra)
1190
+
1191
+ if has_na and not is_str:
1192
+ # don't worry about comparing how NaT is converted
1193
+ sa = np.delete(sa, 3)
1194
+ a = np.delete(a, 3)
1195
+
1196
+ if input_dtype.startswith("M"):
1197
+ assert_array_equal(sa, a.astype("U"))
1198
+ else:
1199
+ # The timedelta to unicode cast produces strings
1200
+ # that aren't round-trippable and we don't want to
1201
+ # reproduce that behavior in stringdtype
1202
+ assert_array_equal(sa, a.astype("int64").astype("U"))
1203
+
1204
+
1205
+ def test_nat_casts():
1206
+ s = 'nat'
1207
+ all_nats = itertools.product(*zip(s.upper(), s.lower()))
1208
+ all_nats = list(map(''.join, all_nats))
1209
+ NaT_dt = np.datetime64('NaT')
1210
+ NaT_td = np.timedelta64('NaT')
1211
+ for na_object in [np._NoValue, None, np.nan, 'nat', '']:
1212
+ # numpy treats empty string and all case combinations of 'nat' as NaT
1213
+ dtype = StringDType(na_object=na_object)
1214
+ arr = np.array([''] + all_nats, dtype=dtype)
1215
+ dt_array = arr.astype('M8[s]')
1216
+ td_array = arr.astype('m8[s]')
1217
+ assert_array_equal(dt_array, NaT_dt)
1218
+ assert_array_equal(td_array, NaT_td)
1219
+
1220
+ if na_object is np._NoValue:
1221
+ output_object = 'NaT'
1222
+ else:
1223
+ output_object = na_object
1224
+
1225
+ for arr in [dt_array, td_array]:
1226
+ assert_array_equal(
1227
+ arr.astype(dtype),
1228
+ np.array([output_object] * arr.size, dtype=dtype))
1229
+
1230
+
1231
+ def test_nat_conversion():
1232
+ for nat in [np.datetime64("NaT", "s"), np.timedelta64("NaT", "s")]:
1233
+ with pytest.raises(ValueError, match="string coercion is disabled"):
1234
+ np.array(["a", nat], dtype=StringDType(coerce=False))
1235
+
1236
+
1237
+ def test_growing_strings(dtype):
1238
+ # growing a string leads to a heap allocation, this tests to make sure
1239
+ # we do that bookkeeping correctly for all possible starting cases
1240
+ data = [
1241
+ "hello", # a short string
1242
+ "abcdefghijklmnopqestuvwxyz", # a medium heap-allocated string
1243
+ "hello" * 200, # a long heap-allocated string
1244
+ ]
1245
+
1246
+ arr = np.array(data, dtype=dtype)
1247
+ uarr = np.array(data, dtype=str)
1248
+
1249
+ for _ in range(5):
1250
+ arr = arr + arr
1251
+ uarr = uarr + uarr
1252
+
1253
+ assert_array_equal(arr, uarr)
1254
+
1255
+
1256
+ def test_assign_medium_strings():
1257
+ # see gh-29261
1258
+ N = 9
1259
+ src = np.array(
1260
+ (
1261
+ ['0' * 256] * 3 + ['0' * 255] + ['0' * 256] + ['0' * 255] +
1262
+ ['0' * 256] * 2 + ['0' * 255]
1263
+ ), dtype='T')
1264
+ dst = np.array(
1265
+ (
1266
+ ['0' * 255] + ['0' * 256] * 2 + ['0' * 255] + ['0' * 256] +
1267
+ ['0' * 255] + [''] * 5
1268
+ ), dtype='T')
1269
+
1270
+ dst[1:N + 1] = src
1271
+ assert_array_equal(dst[1:N + 1], src)
1272
+
1273
+
1274
+ UFUNC_TEST_DATA = [
1275
+ "hello" * 10,
1276
+ "Ae¢☃€ 😊" * 20,
1277
+ "entry\nwith\nnewlines",
1278
+ "entry\twith\ttabs",
1279
+ ]
1280
+
1281
+
1282
+ @pytest.fixture
1283
+ def string_array(dtype):
1284
+ return np.array(UFUNC_TEST_DATA, dtype=dtype)
1285
+
1286
+
1287
+ @pytest.fixture
1288
+ def unicode_array():
1289
+ return np.array(UFUNC_TEST_DATA, dtype=np.str_)
1290
+
1291
+
1292
+ NAN_PRESERVING_FUNCTIONS = [
1293
+ "capitalize",
1294
+ "expandtabs",
1295
+ "lower",
1296
+ "lstrip",
1297
+ "rstrip",
1298
+ "splitlines",
1299
+ "strip",
1300
+ "swapcase",
1301
+ "title",
1302
+ "upper",
1303
+ ]
1304
+
1305
+ BOOL_OUTPUT_FUNCTIONS = [
1306
+ "isalnum",
1307
+ "isalpha",
1308
+ "isdigit",
1309
+ "islower",
1310
+ "isspace",
1311
+ "istitle",
1312
+ "isupper",
1313
+ "isnumeric",
1314
+ "isdecimal",
1315
+ ]
1316
+
1317
+ UNARY_FUNCTIONS = [
1318
+ "str_len",
1319
+ "capitalize",
1320
+ "expandtabs",
1321
+ "isalnum",
1322
+ "isalpha",
1323
+ "isdigit",
1324
+ "islower",
1325
+ "isspace",
1326
+ "istitle",
1327
+ "isupper",
1328
+ "lower",
1329
+ "lstrip",
1330
+ "rstrip",
1331
+ "splitlines",
1332
+ "strip",
1333
+ "swapcase",
1334
+ "title",
1335
+ "upper",
1336
+ "isnumeric",
1337
+ "isdecimal",
1338
+ "isalnum",
1339
+ "islower",
1340
+ "istitle",
1341
+ "isupper",
1342
+ ]
1343
+
1344
+ UNIMPLEMENTED_VEC_STRING_FUNCTIONS = [
1345
+ "capitalize",
1346
+ "expandtabs",
1347
+ "lower",
1348
+ "splitlines",
1349
+ "swapcase",
1350
+ "title",
1351
+ "upper",
1352
+ ]
1353
+
1354
+ ONLY_IN_NP_CHAR = [
1355
+ "join",
1356
+ "split",
1357
+ "rsplit",
1358
+ "splitlines"
1359
+ ]
1360
+
1361
+
1362
+ @pytest.mark.parametrize("function_name", UNARY_FUNCTIONS)
1363
+ def test_unary(string_array, unicode_array, function_name):
1364
+ if function_name in ONLY_IN_NP_CHAR:
1365
+ func = getattr(np.char, function_name)
1366
+ else:
1367
+ func = getattr(np.strings, function_name)
1368
+ dtype = string_array.dtype
1369
+ sres = func(string_array)
1370
+ ures = func(unicode_array)
1371
+ if sres.dtype == StringDType():
1372
+ ures = ures.astype(StringDType())
1373
+ assert_array_equal(sres, ures)
1374
+
1375
+ if not hasattr(dtype, "na_object"):
1376
+ return
1377
+
1378
+ is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0]
1379
+ is_str = isinstance(dtype.na_object, str)
1380
+ na_arr = np.insert(string_array, 0, dtype.na_object)
1381
+
1382
+ if function_name in UNIMPLEMENTED_VEC_STRING_FUNCTIONS:
1383
+ if not is_str:
1384
+ # to avoid these errors we'd need to add NA support to _vec_string
1385
+ with pytest.raises((ValueError, TypeError)):
1386
+ func(na_arr)
1387
+ elif function_name == "splitlines":
1388
+ assert func(na_arr)[0] == func(dtype.na_object)[()]
1389
+ else:
1390
+ assert func(na_arr)[0] == func(dtype.na_object)
1391
+ return
1392
+ if function_name == "str_len" and not is_str:
1393
+ # str_len always errors for any non-string null, even NA ones because
1394
+ # it has an integer result
1395
+ with pytest.raises(ValueError):
1396
+ func(na_arr)
1397
+ return
1398
+ if function_name in BOOL_OUTPUT_FUNCTIONS:
1399
+ if is_nan:
1400
+ assert func(na_arr)[0] is np.False_
1401
+ elif is_str:
1402
+ assert func(na_arr)[0] == func(dtype.na_object)
1403
+ else:
1404
+ with pytest.raises(ValueError):
1405
+ func(na_arr)
1406
+ return
1407
+ if not (is_nan or is_str):
1408
+ with pytest.raises(ValueError):
1409
+ func(na_arr)
1410
+ return
1411
+ res = func(na_arr)
1412
+ if is_nan and function_name in NAN_PRESERVING_FUNCTIONS:
1413
+ assert res[0] is dtype.na_object
1414
+ elif is_str:
1415
+ assert res[0] == func(dtype.na_object)
1416
+
1417
+
1418
+ unicode_bug_fail = pytest.mark.xfail(
1419
+ reason="unicode output width is buggy", strict=True
1420
+ )
1421
+
1422
+ # None means that the argument is a string array
1423
+ BINARY_FUNCTIONS = [
1424
+ ("add", (None, None)),
1425
+ ("multiply", (None, 2)),
1426
+ ("mod", ("format: %s", None)),
1427
+ ("center", (None, 25)),
1428
+ ("count", (None, "A")),
1429
+ ("encode", (None, "UTF-8")),
1430
+ ("endswith", (None, "lo")),
1431
+ ("find", (None, "A")),
1432
+ ("index", (None, "e")),
1433
+ ("join", ("-", None)),
1434
+ ("ljust", (None, 12)),
1435
+ ("lstrip", (None, "A")),
1436
+ ("partition", (None, "A")),
1437
+ ("replace", (None, "A", "B")),
1438
+ ("rfind", (None, "A")),
1439
+ ("rindex", (None, "e")),
1440
+ ("rjust", (None, 12)),
1441
+ ("rsplit", (None, "A")),
1442
+ ("rstrip", (None, "A")),
1443
+ ("rpartition", (None, "A")),
1444
+ ("split", (None, "A")),
1445
+ ("strip", (None, "A")),
1446
+ ("startswith", (None, "A")),
1447
+ ("zfill", (None, 12)),
1448
+ ]
1449
+
1450
+ PASSES_THROUGH_NAN_NULLS = [
1451
+ "add",
1452
+ "center",
1453
+ "ljust",
1454
+ "multiply",
1455
+ "replace",
1456
+ "rjust",
1457
+ "strip",
1458
+ "lstrip",
1459
+ "rstrip",
1460
+ "replace"
1461
+ "zfill",
1462
+ ]
1463
+
1464
+ NULLS_ARE_FALSEY = [
1465
+ "startswith",
1466
+ "endswith",
1467
+ ]
1468
+
1469
+ NULLS_ALWAYS_ERROR = [
1470
+ "count",
1471
+ "find",
1472
+ "rfind",
1473
+ ]
1474
+
1475
+ SUPPORTS_NULLS = (
1476
+ PASSES_THROUGH_NAN_NULLS +
1477
+ NULLS_ARE_FALSEY +
1478
+ NULLS_ALWAYS_ERROR
1479
+ )
1480
+
1481
+
1482
+ def call_func(func, args, array, sanitize=True):
1483
+ if args == (None, None):
1484
+ return func(array, array)
1485
+ if args[0] is None:
1486
+ if sanitize:
1487
+ san_args = tuple(
1488
+ np.array(arg, dtype=array.dtype) if isinstance(arg, str) else
1489
+ arg for arg in args[1:]
1490
+ )
1491
+ else:
1492
+ san_args = args[1:]
1493
+ return func(array, *san_args)
1494
+ if args[1] is None:
1495
+ return func(args[0], array)
1496
+ # shouldn't ever happen
1497
+ assert 0
1498
+
1499
+
1500
+ @pytest.mark.parametrize("function_name, args", BINARY_FUNCTIONS)
1501
+ def test_binary(string_array, unicode_array, function_name, args):
1502
+ if function_name in ONLY_IN_NP_CHAR:
1503
+ func = getattr(np.char, function_name)
1504
+ else:
1505
+ func = getattr(np.strings, function_name)
1506
+ sres = call_func(func, args, string_array)
1507
+ ures = call_func(func, args, unicode_array, sanitize=False)
1508
+ if not isinstance(sres, tuple) and sres.dtype == StringDType():
1509
+ ures = ures.astype(StringDType())
1510
+ assert_array_equal(sres, ures)
1511
+
1512
+ dtype = string_array.dtype
1513
+ if function_name not in SUPPORTS_NULLS or not hasattr(dtype, "na_object"):
1514
+ return
1515
+
1516
+ na_arr = np.insert(string_array, 0, dtype.na_object)
1517
+ is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0]
1518
+ is_str = isinstance(dtype.na_object, str)
1519
+ should_error = not (is_nan or is_str)
1520
+
1521
+ if (
1522
+ (function_name in NULLS_ALWAYS_ERROR and not is_str)
1523
+ or (function_name in PASSES_THROUGH_NAN_NULLS and should_error)
1524
+ or (function_name in NULLS_ARE_FALSEY and should_error)
1525
+ ):
1526
+ with pytest.raises((ValueError, TypeError)):
1527
+ call_func(func, args, na_arr)
1528
+ return
1529
+
1530
+ res = call_func(func, args, na_arr)
1531
+
1532
+ if is_str:
1533
+ assert res[0] == call_func(func, args, na_arr[:1])
1534
+ elif function_name in NULLS_ARE_FALSEY:
1535
+ assert res[0] is np.False_
1536
+ elif function_name in PASSES_THROUGH_NAN_NULLS:
1537
+ assert res[0] is dtype.na_object
1538
+ else:
1539
+ # shouldn't ever get here
1540
+ assert 0
1541
+
1542
+
1543
+ @pytest.mark.parametrize("function, expected", [
1544
+ (np.strings.find, [[2, -1], [1, -1]]),
1545
+ (np.strings.startswith, [[False, False], [True, False]])])
1546
+ @pytest.mark.parametrize("start, stop", [
1547
+ (1, 4),
1548
+ (np.int8(1), np.int8(4)),
1549
+ (np.array([1, 1], dtype='u2'), np.array([4, 4], dtype='u2'))])
1550
+ def test_non_default_start_stop(function, start, stop, expected):
1551
+ a = np.array([["--🐍--", "--🦜--"],
1552
+ ["-🐍---", "-🦜---"]], "T")
1553
+ indx = function(a, "🐍", start, stop)
1554
+ assert_array_equal(indx, expected)
1555
+
1556
+
1557
+ @pytest.mark.parametrize("count", [2, np.int8(2), np.array([2, 2], 'u2')])
1558
+ def test_replace_non_default_repeat(count):
1559
+ a = np.array(["🐍--", "🦜-🦜-"], "T")
1560
+ result = np.strings.replace(a, "🦜-", "🦜†", count)
1561
+ assert_array_equal(result, np.array(["🐍--", "🦜†🦜†"], "T"))
1562
+
1563
+
1564
+ def test_strip_ljust_rjust_consistency(string_array, unicode_array):
1565
+ rjs = np.char.rjust(string_array, 1000)
1566
+ rju = np.char.rjust(unicode_array, 1000)
1567
+
1568
+ ljs = np.char.ljust(string_array, 1000)
1569
+ lju = np.char.ljust(unicode_array, 1000)
1570
+
1571
+ assert_array_equal(
1572
+ np.char.lstrip(rjs),
1573
+ np.char.lstrip(rju).astype(StringDType()),
1574
+ )
1575
+
1576
+ assert_array_equal(
1577
+ np.char.rstrip(ljs),
1578
+ np.char.rstrip(lju).astype(StringDType()),
1579
+ )
1580
+
1581
+ assert_array_equal(
1582
+ np.char.strip(ljs),
1583
+ np.char.strip(lju).astype(StringDType()),
1584
+ )
1585
+
1586
+ assert_array_equal(
1587
+ np.char.strip(rjs),
1588
+ np.char.strip(rju).astype(StringDType()),
1589
+ )
1590
+
1591
+
1592
+ def test_unset_na_coercion():
1593
+ # a dtype instance with an unset na object is compatible
1594
+ # with a dtype that has one set
1595
+
1596
+ # this test uses the "add" and "equal" ufunc but all ufuncs that
1597
+ # accept more than one string argument and produce a string should
1598
+ # behave this way
1599
+ # TODO: generalize to more ufuncs
1600
+ inp = ["hello", "world"]
1601
+ arr = np.array(inp, dtype=StringDType(na_object=None))
1602
+ for op_dtype in [None, StringDType(), StringDType(coerce=False),
1603
+ StringDType(na_object=None)]:
1604
+ if op_dtype is None:
1605
+ op = "2"
1606
+ else:
1607
+ op = np.array("2", dtype=op_dtype)
1608
+ res = arr + op
1609
+ assert_array_equal(res, ["hello2", "world2"])
1610
+
1611
+ # dtype instances with distinct explicitly set NA objects are incompatible
1612
+ for op_dtype in [StringDType(na_object=pd_NA), StringDType(na_object="")]:
1613
+ op = np.array("2", dtype=op_dtype)
1614
+ with pytest.raises(TypeError):
1615
+ arr + op
1616
+
1617
+ # comparisons only consider the na_object
1618
+ for op_dtype in [None, StringDType(), StringDType(coerce=True),
1619
+ StringDType(na_object=None)]:
1620
+ if op_dtype is None:
1621
+ op = inp
1622
+ else:
1623
+ op = np.array(inp, dtype=op_dtype)
1624
+ assert_array_equal(arr, op)
1625
+
1626
+ for op_dtype in [StringDType(na_object=pd_NA),
1627
+ StringDType(na_object=np.nan)]:
1628
+ op = np.array(inp, dtype=op_dtype)
1629
+ with pytest.raises(TypeError):
1630
+ arr == op
1631
+
1632
+
1633
+ def test_repeat(string_array):
1634
+ res = string_array.repeat(1000)
1635
+ # Create an empty array with expanded dimension, and fill it. Then,
1636
+ # reshape it to the expected result.
1637
+ expected = np.empty_like(string_array, shape=string_array.shape + (1000,))
1638
+ expected[...] = string_array[:, np.newaxis]
1639
+ expected = expected.reshape(-1)
1640
+
1641
+ assert_array_equal(res, expected, strict=True)
1642
+
1643
+
1644
+ @pytest.mark.parametrize("tile", [1, 6, (2, 5)])
1645
+ def test_accumulation(string_array, tile):
1646
+ """Accumulation is odd for StringDType but tests dtypes with references.
1647
+ """
1648
+ # Fill with mostly empty strings to not create absurdly big strings
1649
+ arr = np.zeros_like(string_array, shape=(100,))
1650
+ arr[:len(string_array)] = string_array
1651
+ arr[-len(string_array):] = string_array
1652
+
1653
+ # Bloat size a bit (get above thresholds and test >1 ndim).
1654
+ arr = np.tile(string_array, tile)
1655
+
1656
+ res = np.add.accumulate(arr, axis=0)
1657
+ res_obj = np.add.accumulate(arr.astype(object), axis=0)
1658
+ assert_array_equal(res, res_obj.astype(arr.dtype), strict=True)
1659
+
1660
+ if arr.ndim > 1:
1661
+ res = np.add.accumulate(arr, axis=-1)
1662
+ res_obj = np.add.accumulate(arr.astype(object), axis=-1)
1663
+
1664
+ assert_array_equal(res, res_obj.astype(arr.dtype), strict=True)
1665
+
1666
+
1667
+ class TestImplementation:
1668
+ """Check that strings are stored in the arena when possible.
1669
+
1670
+ This tests implementation details, so should be adjusted if
1671
+ the implementation changes.
1672
+ """
1673
+
1674
+ @classmethod
1675
+ def setup_class(cls):
1676
+ cls.MISSING = 0x80
1677
+ cls.INITIALIZED = 0x40
1678
+ cls.OUTSIDE_ARENA = 0x20
1679
+ cls.LONG = 0x10
1680
+ cls.dtype = StringDType(na_object=np.nan)
1681
+ cls.sizeofstr = cls.dtype.itemsize
1682
+ sp = cls.dtype.itemsize // 2 # pointer size = sizeof(size_t)
1683
+ # Below, size is not strictly correct, since it really uses
1684
+ # 7 (or 3) bytes, but good enough for the tests here.
1685
+ cls.view_dtype = np.dtype([
1686
+ ('offset', f'u{sp}'),
1687
+ ('size', f'u{sp // 2}'),
1688
+ ('xsiz', f'V{sp // 2 - 1}'),
1689
+ ('size_and_flags', 'u1'),
1690
+ ] if sys.byteorder == 'little' else [
1691
+ ('size_and_flags', 'u1'),
1692
+ ('xsiz', f'V{sp // 2 - 1}'),
1693
+ ('size', f'u{sp // 2}'),
1694
+ ('offset', f'u{sp}'),
1695
+ ])
1696
+ cls.s_empty = ""
1697
+ cls.s_short = "01234"
1698
+ cls.s_medium = "abcdefghijklmnopqrstuvwxyz"
1699
+ cls.s_long = "-=+" * 100
1700
+ cls.a = np.array(
1701
+ [cls.s_empty, cls.s_short, cls.s_medium, cls.s_long],
1702
+ cls.dtype)
1703
+
1704
+ def get_view(self, a):
1705
+ # Cannot view a StringDType as anything else directly, since
1706
+ # it has references. So, we use a stride trick hack.
1707
+ from numpy.lib._stride_tricks_impl import DummyArray
1708
+ interface = dict(a.__array_interface__)
1709
+ interface['descr'] = self.view_dtype.descr
1710
+ interface['typestr'] = self.view_dtype.str
1711
+ return np.asarray(DummyArray(interface, base=a))
1712
+
1713
+ def get_flags(self, a):
1714
+ return self.get_view(a)['size_and_flags'] & 0xf0
1715
+
1716
+ def is_short(self, a):
1717
+ return self.get_flags(a) == self.INITIALIZED | self.OUTSIDE_ARENA
1718
+
1719
+ def is_on_heap(self, a):
1720
+ return self.get_flags(a) == (self.INITIALIZED
1721
+ | self.OUTSIDE_ARENA
1722
+ | self.LONG)
1723
+
1724
+ def is_missing(self, a):
1725
+ return self.get_flags(a) & self.MISSING == self.MISSING
1726
+
1727
+ def in_arena(self, a):
1728
+ return (self.get_flags(a) & (self.INITIALIZED | self.OUTSIDE_ARENA)
1729
+ == self.INITIALIZED)
1730
+
1731
+ def test_setup(self):
1732
+ is_short = self.is_short(self.a)
1733
+ length = np.strings.str_len(self.a)
1734
+ assert_array_equal(is_short, (length > 0) & (length <= 15))
1735
+ assert_array_equal(self.in_arena(self.a), [False, False, True, True])
1736
+ assert_array_equal(self.is_on_heap(self.a), False)
1737
+ assert_array_equal(self.is_missing(self.a), False)
1738
+ view = self.get_view(self.a)
1739
+ sizes = np.where(is_short, view['size_and_flags'] & 0xf,
1740
+ view['size'])
1741
+ assert_array_equal(sizes, np.strings.str_len(self.a))
1742
+ assert_array_equal(view['xsiz'][2:],
1743
+ np.void(b'\x00' * (self.sizeofstr // 4 - 1)))
1744
+ # Check that the medium string uses only 1 byte for its length
1745
+ # in the arena, while the long string takes 8 (or 4).
1746
+ offsets = view['offset']
1747
+ assert offsets[2] == 1
1748
+ assert offsets[3] == 1 + len(self.s_medium) + self.sizeofstr // 2
1749
+
1750
+ def test_empty(self):
1751
+ e = np.empty((3,), self.dtype)
1752
+ assert_array_equal(self.get_flags(e), 0)
1753
+ assert_array_equal(e, "")
1754
+
1755
+ def test_zeros(self):
1756
+ z = np.zeros((2,), self.dtype)
1757
+ assert_array_equal(self.get_flags(z), 0)
1758
+ assert_array_equal(z, "")
1759
+
1760
+ def test_copy(self):
1761
+ for c in [self.a.copy(), copy.copy(self.a), copy.deepcopy(self.a)]:
1762
+ assert_array_equal(self.get_flags(c), self.get_flags(self.a))
1763
+ assert_array_equal(c, self.a)
1764
+ offsets = self.get_view(c)['offset']
1765
+ assert offsets[2] == 1
1766
+ assert offsets[3] == 1 + len(self.s_medium) + self.sizeofstr // 2
1767
+
1768
+ def test_arena_use_with_setting(self):
1769
+ c = np.zeros_like(self.a)
1770
+ assert_array_equal(self.get_flags(c), 0)
1771
+ c[:] = self.a
1772
+ assert_array_equal(self.get_flags(c), self.get_flags(self.a))
1773
+ assert_array_equal(c, self.a)
1774
+
1775
+ def test_arena_reuse_with_setting(self):
1776
+ c = self.a.copy()
1777
+ c[:] = self.a
1778
+ assert_array_equal(self.get_flags(c), self.get_flags(self.a))
1779
+ assert_array_equal(c, self.a)
1780
+
1781
+ def test_arena_reuse_after_missing(self):
1782
+ c = self.a.copy()
1783
+ c[:] = np.nan
1784
+ assert np.all(self.is_missing(c))
1785
+ # Replacing with the original strings, the arena should be reused.
1786
+ c[:] = self.a
1787
+ assert_array_equal(self.get_flags(c), self.get_flags(self.a))
1788
+ assert_array_equal(c, self.a)
1789
+
1790
+ def test_arena_reuse_after_empty(self):
1791
+ c = self.a.copy()
1792
+ c[:] = ""
1793
+ assert_array_equal(c, "")
1794
+ # Replacing with the original strings, the arena should be reused.
1795
+ c[:] = self.a
1796
+ assert_array_equal(self.get_flags(c), self.get_flags(self.a))
1797
+ assert_array_equal(c, self.a)
1798
+
1799
+ def test_arena_reuse_for_shorter(self):
1800
+ c = self.a.copy()
1801
+ # A string slightly shorter than the shortest in the arena
1802
+ # should be used for all strings in the arena.
1803
+ c[:] = self.s_medium[:-1]
1804
+ assert_array_equal(c, self.s_medium[:-1])
1805
+ # first empty string in original was never initialized, so
1806
+ # filling it in now leaves it initialized inside the arena.
1807
+ # second string started as a short string so it can never live
1808
+ # in the arena.
1809
+ in_arena = np.array([True, False, True, True])
1810
+ assert_array_equal(self.in_arena(c), in_arena)
1811
+ # But when a short string is replaced, it will go on the heap.
1812
+ assert_array_equal(self.is_short(c), False)
1813
+ assert_array_equal(self.is_on_heap(c), ~in_arena)
1814
+ # We can put the originals back, and they'll still fit,
1815
+ # and short strings are back as short strings
1816
+ c[:] = self.a
1817
+ assert_array_equal(c, self.a)
1818
+ assert_array_equal(self.in_arena(c), in_arena)
1819
+ assert_array_equal(self.is_short(c), self.is_short(self.a))
1820
+ assert_array_equal(self.is_on_heap(c), False)
1821
+
1822
+ def test_arena_reuse_if_possible(self):
1823
+ c = self.a.copy()
1824
+ # A slightly longer string will not fit in the arena for
1825
+ # the medium string, but will fit for the longer one.
1826
+ c[:] = self.s_medium + "±"
1827
+ assert_array_equal(c, self.s_medium + "±")
1828
+ in_arena_exp = np.strings.str_len(self.a) >= len(self.s_medium) + 1
1829
+ # first entry started uninitialized and empty, so filling it leaves
1830
+ # it in the arena
1831
+ in_arena_exp[0] = True
1832
+ assert not np.all(in_arena_exp == self.in_arena(self.a))
1833
+ assert_array_equal(self.in_arena(c), in_arena_exp)
1834
+ assert_array_equal(self.is_short(c), False)
1835
+ assert_array_equal(self.is_on_heap(c), ~in_arena_exp)
1836
+ # And once outside arena, it stays outside, since offset is lost.
1837
+ # But short strings are used again.
1838
+ c[:] = self.a
1839
+ is_short_exp = self.is_short(self.a)
1840
+ assert_array_equal(c, self.a)
1841
+ assert_array_equal(self.in_arena(c), in_arena_exp)
1842
+ assert_array_equal(self.is_short(c), is_short_exp)
1843
+ assert_array_equal(self.is_on_heap(c), ~in_arena_exp & ~is_short_exp)
1844
+
1845
+ def test_arena_no_reuse_after_short(self):
1846
+ c = self.a.copy()
1847
+ # If we replace a string with a short string, it cannot
1848
+ # go into the arena after because the offset is lost.
1849
+ c[:] = self.s_short
1850
+ assert_array_equal(c, self.s_short)
1851
+ assert_array_equal(self.in_arena(c), False)
1852
+ c[:] = self.a
1853
+ assert_array_equal(c, self.a)
1854
+ assert_array_equal(self.in_arena(c), False)
1855
+ assert_array_equal(self.is_on_heap(c), self.in_arena(self.a))