numpy 2.3.5__cp313-cp313-macosx_14_0_arm64.whl

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

Potentially problematic release.


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

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