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