numba-cuda 0.21.1__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (488) hide show
  1. _numba_cuda_redirector.pth +4 -0
  2. _numba_cuda_redirector.py +89 -0
  3. numba_cuda/VERSION +1 -0
  4. numba_cuda/__init__.py +6 -0
  5. numba_cuda/_version.py +11 -0
  6. numba_cuda/numba/cuda/__init__.py +70 -0
  7. numba_cuda/numba/cuda/_internal/cuda_bf16.py +16394 -0
  8. numba_cuda/numba/cuda/_internal/cuda_fp16.py +8112 -0
  9. numba_cuda/numba/cuda/api.py +577 -0
  10. numba_cuda/numba/cuda/api_util.py +76 -0
  11. numba_cuda/numba/cuda/args.py +72 -0
  12. numba_cuda/numba/cuda/bf16.py +397 -0
  13. numba_cuda/numba/cuda/cache_hints.py +287 -0
  14. numba_cuda/numba/cuda/cext/__init__.py +2 -0
  15. numba_cuda/numba/cuda/cext/_devicearray.cp313-win_amd64.pyd +0 -0
  16. numba_cuda/numba/cuda/cext/_devicearray.cpp +159 -0
  17. numba_cuda/numba/cuda/cext/_devicearray.h +29 -0
  18. numba_cuda/numba/cuda/cext/_dispatcher.cp313-win_amd64.pyd +0 -0
  19. numba_cuda/numba/cuda/cext/_dispatcher.cpp +1098 -0
  20. numba_cuda/numba/cuda/cext/_hashtable.cpp +532 -0
  21. numba_cuda/numba/cuda/cext/_hashtable.h +135 -0
  22. numba_cuda/numba/cuda/cext/_helperlib.c +71 -0
  23. numba_cuda/numba/cuda/cext/_helperlib.cp313-win_amd64.pyd +0 -0
  24. numba_cuda/numba/cuda/cext/_helpermod.c +82 -0
  25. numba_cuda/numba/cuda/cext/_pymodule.h +38 -0
  26. numba_cuda/numba/cuda/cext/_typeconv.cp313-win_amd64.pyd +0 -0
  27. numba_cuda/numba/cuda/cext/_typeconv.cpp +206 -0
  28. numba_cuda/numba/cuda/cext/_typeof.cpp +1159 -0
  29. numba_cuda/numba/cuda/cext/_typeof.h +19 -0
  30. numba_cuda/numba/cuda/cext/capsulethunk.h +111 -0
  31. numba_cuda/numba/cuda/cext/mviewbuf.c +385 -0
  32. numba_cuda/numba/cuda/cext/mviewbuf.cp313-win_amd64.pyd +0 -0
  33. numba_cuda/numba/cuda/cext/typeconv.cpp +212 -0
  34. numba_cuda/numba/cuda/cext/typeconv.hpp +101 -0
  35. numba_cuda/numba/cuda/cg.py +67 -0
  36. numba_cuda/numba/cuda/cgutils.py +1294 -0
  37. numba_cuda/numba/cuda/cloudpickle/__init__.py +21 -0
  38. numba_cuda/numba/cuda/cloudpickle/cloudpickle.py +1598 -0
  39. numba_cuda/numba/cuda/cloudpickle/cloudpickle_fast.py +17 -0
  40. numba_cuda/numba/cuda/codegen.py +541 -0
  41. numba_cuda/numba/cuda/compiler.py +1396 -0
  42. numba_cuda/numba/cuda/core/analysis.py +758 -0
  43. numba_cuda/numba/cuda/core/annotations/__init__.py +0 -0
  44. numba_cuda/numba/cuda/core/annotations/pretty_annotate.py +288 -0
  45. numba_cuda/numba/cuda/core/annotations/type_annotations.py +305 -0
  46. numba_cuda/numba/cuda/core/base.py +1332 -0
  47. numba_cuda/numba/cuda/core/boxing.py +1411 -0
  48. numba_cuda/numba/cuda/core/bytecode.py +728 -0
  49. numba_cuda/numba/cuda/core/byteflow.py +2346 -0
  50. numba_cuda/numba/cuda/core/caching.py +744 -0
  51. numba_cuda/numba/cuda/core/callconv.py +392 -0
  52. numba_cuda/numba/cuda/core/codegen.py +171 -0
  53. numba_cuda/numba/cuda/core/compiler.py +199 -0
  54. numba_cuda/numba/cuda/core/compiler_lock.py +85 -0
  55. numba_cuda/numba/cuda/core/compiler_machinery.py +497 -0
  56. numba_cuda/numba/cuda/core/config.py +650 -0
  57. numba_cuda/numba/cuda/core/consts.py +124 -0
  58. numba_cuda/numba/cuda/core/controlflow.py +989 -0
  59. numba_cuda/numba/cuda/core/entrypoints.py +57 -0
  60. numba_cuda/numba/cuda/core/environment.py +66 -0
  61. numba_cuda/numba/cuda/core/errors.py +917 -0
  62. numba_cuda/numba/cuda/core/event.py +511 -0
  63. numba_cuda/numba/cuda/core/funcdesc.py +330 -0
  64. numba_cuda/numba/cuda/core/generators.py +387 -0
  65. numba_cuda/numba/cuda/core/imputils.py +509 -0
  66. numba_cuda/numba/cuda/core/inline_closurecall.py +1787 -0
  67. numba_cuda/numba/cuda/core/interpreter.py +3617 -0
  68. numba_cuda/numba/cuda/core/ir.py +1812 -0
  69. numba_cuda/numba/cuda/core/ir_utils.py +2638 -0
  70. numba_cuda/numba/cuda/core/optional.py +129 -0
  71. numba_cuda/numba/cuda/core/options.py +262 -0
  72. numba_cuda/numba/cuda/core/postproc.py +249 -0
  73. numba_cuda/numba/cuda/core/pythonapi.py +1859 -0
  74. numba_cuda/numba/cuda/core/registry.py +46 -0
  75. numba_cuda/numba/cuda/core/removerefctpass.py +123 -0
  76. numba_cuda/numba/cuda/core/rewrites/__init__.py +26 -0
  77. numba_cuda/numba/cuda/core/rewrites/ir_print.py +91 -0
  78. numba_cuda/numba/cuda/core/rewrites/registry.py +104 -0
  79. numba_cuda/numba/cuda/core/rewrites/static_binop.py +41 -0
  80. numba_cuda/numba/cuda/core/rewrites/static_getitem.py +189 -0
  81. numba_cuda/numba/cuda/core/rewrites/static_raise.py +100 -0
  82. numba_cuda/numba/cuda/core/sigutils.py +68 -0
  83. numba_cuda/numba/cuda/core/ssa.py +498 -0
  84. numba_cuda/numba/cuda/core/targetconfig.py +330 -0
  85. numba_cuda/numba/cuda/core/tracing.py +231 -0
  86. numba_cuda/numba/cuda/core/transforms.py +956 -0
  87. numba_cuda/numba/cuda/core/typed_passes.py +867 -0
  88. numba_cuda/numba/cuda/core/typeinfer.py +1950 -0
  89. numba_cuda/numba/cuda/core/unsafe/__init__.py +0 -0
  90. numba_cuda/numba/cuda/core/unsafe/bytes.py +67 -0
  91. numba_cuda/numba/cuda/core/unsafe/eh.py +67 -0
  92. numba_cuda/numba/cuda/core/unsafe/refcount.py +98 -0
  93. numba_cuda/numba/cuda/core/untyped_passes.py +1979 -0
  94. numba_cuda/numba/cuda/cpython/builtins.py +1153 -0
  95. numba_cuda/numba/cuda/cpython/charseq.py +1218 -0
  96. numba_cuda/numba/cuda/cpython/cmathimpl.py +560 -0
  97. numba_cuda/numba/cuda/cpython/enumimpl.py +103 -0
  98. numba_cuda/numba/cuda/cpython/iterators.py +167 -0
  99. numba_cuda/numba/cuda/cpython/listobj.py +1326 -0
  100. numba_cuda/numba/cuda/cpython/mathimpl.py +499 -0
  101. numba_cuda/numba/cuda/cpython/numbers.py +1475 -0
  102. numba_cuda/numba/cuda/cpython/rangeobj.py +289 -0
  103. numba_cuda/numba/cuda/cpython/slicing.py +322 -0
  104. numba_cuda/numba/cuda/cpython/tupleobj.py +456 -0
  105. numba_cuda/numba/cuda/cpython/unicode.py +2865 -0
  106. numba_cuda/numba/cuda/cpython/unicode_support.py +1597 -0
  107. numba_cuda/numba/cuda/cpython/unsafe/__init__.py +0 -0
  108. numba_cuda/numba/cuda/cpython/unsafe/numbers.py +64 -0
  109. numba_cuda/numba/cuda/cpython/unsafe/tuple.py +92 -0
  110. numba_cuda/numba/cuda/cuda_paths.py +691 -0
  111. numba_cuda/numba/cuda/cudadecl.py +556 -0
  112. numba_cuda/numba/cuda/cudadrv/__init__.py +14 -0
  113. numba_cuda/numba/cuda/cudadrv/devicearray.py +951 -0
  114. numba_cuda/numba/cuda/cudadrv/devices.py +249 -0
  115. numba_cuda/numba/cuda/cudadrv/driver.py +3222 -0
  116. numba_cuda/numba/cuda/cudadrv/drvapi.py +435 -0
  117. numba_cuda/numba/cuda/cudadrv/dummyarray.py +558 -0
  118. numba_cuda/numba/cuda/cudadrv/enums.py +613 -0
  119. numba_cuda/numba/cuda/cudadrv/error.py +48 -0
  120. numba_cuda/numba/cuda/cudadrv/libs.py +220 -0
  121. numba_cuda/numba/cuda/cudadrv/linkable_code.py +184 -0
  122. numba_cuda/numba/cuda/cudadrv/mappings.py +14 -0
  123. numba_cuda/numba/cuda/cudadrv/ndarray.py +26 -0
  124. numba_cuda/numba/cuda/cudadrv/nvrtc.py +193 -0
  125. numba_cuda/numba/cuda/cudadrv/nvvm.py +756 -0
  126. numba_cuda/numba/cuda/cudadrv/rtapi.py +13 -0
  127. numba_cuda/numba/cuda/cudadrv/runtime.py +34 -0
  128. numba_cuda/numba/cuda/cudaimpl.py +995 -0
  129. numba_cuda/numba/cuda/cudamath.py +149 -0
  130. numba_cuda/numba/cuda/datamodel/__init__.py +7 -0
  131. numba_cuda/numba/cuda/datamodel/cuda_manager.py +66 -0
  132. numba_cuda/numba/cuda/datamodel/cuda_models.py +1446 -0
  133. numba_cuda/numba/cuda/datamodel/cuda_packer.py +224 -0
  134. numba_cuda/numba/cuda/datamodel/cuda_registry.py +22 -0
  135. numba_cuda/numba/cuda/datamodel/cuda_testing.py +153 -0
  136. numba_cuda/numba/cuda/datamodel/manager.py +11 -0
  137. numba_cuda/numba/cuda/datamodel/models.py +9 -0
  138. numba_cuda/numba/cuda/datamodel/packer.py +9 -0
  139. numba_cuda/numba/cuda/datamodel/registry.py +11 -0
  140. numba_cuda/numba/cuda/datamodel/testing.py +11 -0
  141. numba_cuda/numba/cuda/debuginfo.py +903 -0
  142. numba_cuda/numba/cuda/decorators.py +294 -0
  143. numba_cuda/numba/cuda/descriptor.py +35 -0
  144. numba_cuda/numba/cuda/device_init.py +158 -0
  145. numba_cuda/numba/cuda/deviceufunc.py +1021 -0
  146. numba_cuda/numba/cuda/dispatcher.py +2463 -0
  147. numba_cuda/numba/cuda/errors.py +72 -0
  148. numba_cuda/numba/cuda/extending.py +697 -0
  149. numba_cuda/numba/cuda/flags.py +178 -0
  150. numba_cuda/numba/cuda/fp16.py +357 -0
  151. numba_cuda/numba/cuda/include/12/cuda_bf16.h +5118 -0
  152. numba_cuda/numba/cuda/include/12/cuda_bf16.hpp +3865 -0
  153. numba_cuda/numba/cuda/include/12/cuda_fp16.h +5363 -0
  154. numba_cuda/numba/cuda/include/12/cuda_fp16.hpp +3483 -0
  155. numba_cuda/numba/cuda/include/13/cuda_bf16.h +5118 -0
  156. numba_cuda/numba/cuda/include/13/cuda_bf16.hpp +3865 -0
  157. numba_cuda/numba/cuda/include/13/cuda_fp16.h +5363 -0
  158. numba_cuda/numba/cuda/include/13/cuda_fp16.hpp +3483 -0
  159. numba_cuda/numba/cuda/initialize.py +24 -0
  160. numba_cuda/numba/cuda/intrinsic_wrapper.py +41 -0
  161. numba_cuda/numba/cuda/intrinsics.py +382 -0
  162. numba_cuda/numba/cuda/itanium_mangler.py +214 -0
  163. numba_cuda/numba/cuda/kernels/__init__.py +2 -0
  164. numba_cuda/numba/cuda/kernels/reduction.py +265 -0
  165. numba_cuda/numba/cuda/kernels/transpose.py +65 -0
  166. numba_cuda/numba/cuda/libdevice.py +3386 -0
  167. numba_cuda/numba/cuda/libdevicedecl.py +20 -0
  168. numba_cuda/numba/cuda/libdevicefuncs.py +1060 -0
  169. numba_cuda/numba/cuda/libdeviceimpl.py +88 -0
  170. numba_cuda/numba/cuda/locks.py +19 -0
  171. numba_cuda/numba/cuda/lowering.py +1951 -0
  172. numba_cuda/numba/cuda/mathimpl.py +374 -0
  173. numba_cuda/numba/cuda/memory_management/__init__.py +4 -0
  174. numba_cuda/numba/cuda/memory_management/memsys.cu +99 -0
  175. numba_cuda/numba/cuda/memory_management/memsys.cuh +22 -0
  176. numba_cuda/numba/cuda/memory_management/nrt.cu +212 -0
  177. numba_cuda/numba/cuda/memory_management/nrt.cuh +48 -0
  178. numba_cuda/numba/cuda/memory_management/nrt.py +390 -0
  179. numba_cuda/numba/cuda/memory_management/nrt_context.py +438 -0
  180. numba_cuda/numba/cuda/misc/appdirs.py +594 -0
  181. numba_cuda/numba/cuda/misc/cffiimpl.py +24 -0
  182. numba_cuda/numba/cuda/misc/coverage_support.py +43 -0
  183. numba_cuda/numba/cuda/misc/dump_style.py +41 -0
  184. numba_cuda/numba/cuda/misc/findlib.py +75 -0
  185. numba_cuda/numba/cuda/misc/firstlinefinder.py +96 -0
  186. numba_cuda/numba/cuda/misc/gdb_hook.py +240 -0
  187. numba_cuda/numba/cuda/misc/literal.py +28 -0
  188. numba_cuda/numba/cuda/misc/llvm_pass_timings.py +412 -0
  189. numba_cuda/numba/cuda/misc/special.py +94 -0
  190. numba_cuda/numba/cuda/models.py +56 -0
  191. numba_cuda/numba/cuda/np/arraymath.py +5130 -0
  192. numba_cuda/numba/cuda/np/arrayobj.py +7635 -0
  193. numba_cuda/numba/cuda/np/extensions.py +11 -0
  194. numba_cuda/numba/cuda/np/linalg.py +3087 -0
  195. numba_cuda/numba/cuda/np/math/__init__.py +0 -0
  196. numba_cuda/numba/cuda/np/math/cmathimpl.py +558 -0
  197. numba_cuda/numba/cuda/np/math/mathimpl.py +487 -0
  198. numba_cuda/numba/cuda/np/math/numbers.py +1461 -0
  199. numba_cuda/numba/cuda/np/npdatetime.py +969 -0
  200. numba_cuda/numba/cuda/np/npdatetime_helpers.py +217 -0
  201. numba_cuda/numba/cuda/np/npyfuncs.py +1808 -0
  202. numba_cuda/numba/cuda/np/npyimpl.py +1027 -0
  203. numba_cuda/numba/cuda/np/numpy_support.py +798 -0
  204. numba_cuda/numba/cuda/np/polynomial/__init__.py +4 -0
  205. numba_cuda/numba/cuda/np/polynomial/polynomial_core.py +242 -0
  206. numba_cuda/numba/cuda/np/polynomial/polynomial_functions.py +380 -0
  207. numba_cuda/numba/cuda/np/ufunc/__init__.py +4 -0
  208. numba_cuda/numba/cuda/np/ufunc/decorators.py +203 -0
  209. numba_cuda/numba/cuda/np/ufunc/sigparse.py +68 -0
  210. numba_cuda/numba/cuda/np/ufunc/ufuncbuilder.py +65 -0
  211. numba_cuda/numba/cuda/np/ufunc_db.py +1282 -0
  212. numba_cuda/numba/cuda/np/unsafe/__init__.py +0 -0
  213. numba_cuda/numba/cuda/np/unsafe/ndarray.py +84 -0
  214. numba_cuda/numba/cuda/nvvmutils.py +254 -0
  215. numba_cuda/numba/cuda/printimpl.py +126 -0
  216. numba_cuda/numba/cuda/random.py +308 -0
  217. numba_cuda/numba/cuda/reshape_funcs.cu +156 -0
  218. numba_cuda/numba/cuda/serialize.py +267 -0
  219. numba_cuda/numba/cuda/simulator/__init__.py +63 -0
  220. numba_cuda/numba/cuda/simulator/_internal/__init__.py +4 -0
  221. numba_cuda/numba/cuda/simulator/_internal/cuda_bf16.py +2 -0
  222. numba_cuda/numba/cuda/simulator/api.py +179 -0
  223. numba_cuda/numba/cuda/simulator/bf16.py +4 -0
  224. numba_cuda/numba/cuda/simulator/compiler.py +38 -0
  225. numba_cuda/numba/cuda/simulator/cudadrv/__init__.py +11 -0
  226. numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +462 -0
  227. numba_cuda/numba/cuda/simulator/cudadrv/devices.py +122 -0
  228. numba_cuda/numba/cuda/simulator/cudadrv/driver.py +66 -0
  229. numba_cuda/numba/cuda/simulator/cudadrv/drvapi.py +7 -0
  230. numba_cuda/numba/cuda/simulator/cudadrv/dummyarray.py +7 -0
  231. numba_cuda/numba/cuda/simulator/cudadrv/error.py +10 -0
  232. numba_cuda/numba/cuda/simulator/cudadrv/libs.py +10 -0
  233. numba_cuda/numba/cuda/simulator/cudadrv/linkable_code.py +61 -0
  234. numba_cuda/numba/cuda/simulator/cudadrv/nvrtc.py +11 -0
  235. numba_cuda/numba/cuda/simulator/cudadrv/nvvm.py +32 -0
  236. numba_cuda/numba/cuda/simulator/cudadrv/runtime.py +22 -0
  237. numba_cuda/numba/cuda/simulator/dispatcher.py +11 -0
  238. numba_cuda/numba/cuda/simulator/kernel.py +320 -0
  239. numba_cuda/numba/cuda/simulator/kernelapi.py +509 -0
  240. numba_cuda/numba/cuda/simulator/memory_management/__init__.py +4 -0
  241. numba_cuda/numba/cuda/simulator/memory_management/nrt.py +21 -0
  242. numba_cuda/numba/cuda/simulator/reduction.py +19 -0
  243. numba_cuda/numba/cuda/simulator/tests/support.py +4 -0
  244. numba_cuda/numba/cuda/simulator/vector_types.py +65 -0
  245. numba_cuda/numba/cuda/simulator_init.py +18 -0
  246. numba_cuda/numba/cuda/stubs.py +635 -0
  247. numba_cuda/numba/cuda/target.py +505 -0
  248. numba_cuda/numba/cuda/testing.py +347 -0
  249. numba_cuda/numba/cuda/tests/__init__.py +62 -0
  250. numba_cuda/numba/cuda/tests/benchmarks/__init__.py +0 -0
  251. numba_cuda/numba/cuda/tests/benchmarks/test_kernel_launch.py +119 -0
  252. numba_cuda/numba/cuda/tests/cloudpickle_main_class.py +9 -0
  253. numba_cuda/numba/cuda/tests/core/serialize_usecases.py +113 -0
  254. numba_cuda/numba/cuda/tests/core/test_itanium_mangler.py +83 -0
  255. numba_cuda/numba/cuda/tests/core/test_serialize.py +371 -0
  256. numba_cuda/numba/cuda/tests/cudadrv/__init__.py +9 -0
  257. numba_cuda/numba/cuda/tests/cudadrv/test_array_attr.py +147 -0
  258. numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +161 -0
  259. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py +397 -0
  260. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_auto_context.py +24 -0
  261. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +180 -0
  262. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +313 -0
  263. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +187 -0
  264. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +621 -0
  265. numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +247 -0
  266. numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +100 -0
  267. numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +198 -0
  268. numba_cuda/numba/cuda/tests/cudadrv/test_events.py +53 -0
  269. numba_cuda/numba/cuda/tests/cudadrv/test_host_alloc.py +72 -0
  270. numba_cuda/numba/cuda/tests/cudadrv/test_init.py +138 -0
  271. numba_cuda/numba/cuda/tests/cudadrv/test_inline_ptx.py +43 -0
  272. numba_cuda/numba/cuda/tests/cudadrv/test_is_fp16.py +15 -0
  273. numba_cuda/numba/cuda/tests/cudadrv/test_linkable_code.py +58 -0
  274. numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +348 -0
  275. numba_cuda/numba/cuda/tests/cudadrv/test_managed_alloc.py +128 -0
  276. numba_cuda/numba/cuda/tests/cudadrv/test_module_callbacks.py +301 -0
  277. numba_cuda/numba/cuda/tests/cudadrv/test_nvjitlink.py +174 -0
  278. numba_cuda/numba/cuda/tests/cudadrv/test_nvrtc.py +28 -0
  279. numba_cuda/numba/cuda/tests/cudadrv/test_nvvm_driver.py +185 -0
  280. numba_cuda/numba/cuda/tests/cudadrv/test_pinned.py +39 -0
  281. numba_cuda/numba/cuda/tests/cudadrv/test_profiler.py +23 -0
  282. numba_cuda/numba/cuda/tests/cudadrv/test_reset_device.py +38 -0
  283. numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +48 -0
  284. numba_cuda/numba/cuda/tests/cudadrv/test_select_device.py +44 -0
  285. numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +127 -0
  286. numba_cuda/numba/cuda/tests/cudapy/__init__.py +9 -0
  287. numba_cuda/numba/cuda/tests/cudapy/cache_usecases.py +231 -0
  288. numba_cuda/numba/cuda/tests/cudapy/cache_with_cpu_usecases.py +50 -0
  289. numba_cuda/numba/cuda/tests/cudapy/cg_cache_usecases.py +36 -0
  290. numba_cuda/numba/cuda/tests/cudapy/complex_usecases.py +116 -0
  291. numba_cuda/numba/cuda/tests/cudapy/enum_usecases.py +59 -0
  292. numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +62 -0
  293. numba_cuda/numba/cuda/tests/cudapy/jitlink.ptx +28 -0
  294. numba_cuda/numba/cuda/tests/cudapy/overload_usecases.py +33 -0
  295. numba_cuda/numba/cuda/tests/cudapy/recursion_usecases.py +104 -0
  296. numba_cuda/numba/cuda/tests/cudapy/test_alignment.py +47 -0
  297. numba_cuda/numba/cuda/tests/cudapy/test_analysis.py +1122 -0
  298. numba_cuda/numba/cuda/tests/cudapy/test_array.py +344 -0
  299. numba_cuda/numba/cuda/tests/cudapy/test_array_alignment.py +268 -0
  300. numba_cuda/numba/cuda/tests/cudapy/test_array_args.py +203 -0
  301. numba_cuda/numba/cuda/tests/cudapy/test_array_methods.py +63 -0
  302. numba_cuda/numba/cuda/tests/cudapy/test_array_reductions.py +360 -0
  303. numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +1815 -0
  304. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16.py +599 -0
  305. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16_bindings.py +377 -0
  306. numba_cuda/numba/cuda/tests/cudapy/test_blackscholes.py +160 -0
  307. numba_cuda/numba/cuda/tests/cudapy/test_boolean.py +27 -0
  308. numba_cuda/numba/cuda/tests/cudapy/test_byteflow.py +98 -0
  309. numba_cuda/numba/cuda/tests/cudapy/test_cache_hints.py +210 -0
  310. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +683 -0
  311. numba_cuda/numba/cuda/tests/cudapy/test_casting.py +265 -0
  312. numba_cuda/numba/cuda/tests/cudapy/test_cffi.py +42 -0
  313. numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +718 -0
  314. numba_cuda/numba/cuda/tests/cudapy/test_complex.py +370 -0
  315. numba_cuda/numba/cuda/tests/cudapy/test_complex_kernel.py +23 -0
  316. numba_cuda/numba/cuda/tests/cudapy/test_const_string.py +142 -0
  317. numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +178 -0
  318. numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +193 -0
  319. numba_cuda/numba/cuda/tests/cudapy/test_copy_propagate.py +131 -0
  320. numba_cuda/numba/cuda/tests/cudapy/test_cuda_array_interface.py +438 -0
  321. numba_cuda/numba/cuda/tests/cudapy/test_cuda_jit_no_types.py +94 -0
  322. numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +101 -0
  323. numba_cuda/numba/cuda/tests/cudapy/test_debug.py +105 -0
  324. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +889 -0
  325. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo_types.py +476 -0
  326. numba_cuda/numba/cuda/tests/cudapy/test_device_func.py +500 -0
  327. numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +820 -0
  328. numba_cuda/numba/cuda/tests/cudapy/test_enums.py +152 -0
  329. numba_cuda/numba/cuda/tests/cudapy/test_errors.py +111 -0
  330. numba_cuda/numba/cuda/tests/cudapy/test_exception.py +170 -0
  331. numba_cuda/numba/cuda/tests/cudapy/test_extending.py +1088 -0
  332. numba_cuda/numba/cuda/tests/cudapy/test_extending_types.py +71 -0
  333. numba_cuda/numba/cuda/tests/cudapy/test_fastmath.py +265 -0
  334. numba_cuda/numba/cuda/tests/cudapy/test_flow_control.py +1433 -0
  335. numba_cuda/numba/cuda/tests/cudapy/test_forall.py +57 -0
  336. numba_cuda/numba/cuda/tests/cudapy/test_freevar.py +34 -0
  337. numba_cuda/numba/cuda/tests/cudapy/test_frexp_ldexp.py +69 -0
  338. numba_cuda/numba/cuda/tests/cudapy/test_globals.py +62 -0
  339. numba_cuda/numba/cuda/tests/cudapy/test_gufunc.py +474 -0
  340. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scalar.py +167 -0
  341. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scheduling.py +92 -0
  342. numba_cuda/numba/cuda/tests/cudapy/test_idiv.py +39 -0
  343. numba_cuda/numba/cuda/tests/cudapy/test_inline.py +170 -0
  344. numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +255 -0
  345. numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +1219 -0
  346. numba_cuda/numba/cuda/tests/cudapy/test_ipc.py +263 -0
  347. numba_cuda/numba/cuda/tests/cudapy/test_ir.py +598 -0
  348. numba_cuda/numba/cuda/tests/cudapy/test_ir_utils.py +276 -0
  349. numba_cuda/numba/cuda/tests/cudapy/test_iterators.py +101 -0
  350. numba_cuda/numba/cuda/tests/cudapy/test_lang.py +68 -0
  351. numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +123 -0
  352. numba_cuda/numba/cuda/tests/cudapy/test_libdevice.py +194 -0
  353. numba_cuda/numba/cuda/tests/cudapy/test_lineinfo.py +220 -0
  354. numba_cuda/numba/cuda/tests/cudapy/test_localmem.py +173 -0
  355. numba_cuda/numba/cuda/tests/cudapy/test_make_function_to_jit_function.py +364 -0
  356. numba_cuda/numba/cuda/tests/cudapy/test_mandel.py +47 -0
  357. numba_cuda/numba/cuda/tests/cudapy/test_math.py +842 -0
  358. numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +76 -0
  359. numba_cuda/numba/cuda/tests/cudapy/test_minmax.py +78 -0
  360. numba_cuda/numba/cuda/tests/cudapy/test_montecarlo.py +25 -0
  361. numba_cuda/numba/cuda/tests/cudapy/test_multigpu.py +145 -0
  362. numba_cuda/numba/cuda/tests/cudapy/test_multiprocessing.py +39 -0
  363. numba_cuda/numba/cuda/tests/cudapy/test_multithreads.py +82 -0
  364. numba_cuda/numba/cuda/tests/cudapy/test_nondet.py +53 -0
  365. numba_cuda/numba/cuda/tests/cudapy/test_operator.py +504 -0
  366. numba_cuda/numba/cuda/tests/cudapy/test_optimization.py +93 -0
  367. numba_cuda/numba/cuda/tests/cudapy/test_overload.py +402 -0
  368. numba_cuda/numba/cuda/tests/cudapy/test_powi.py +128 -0
  369. numba_cuda/numba/cuda/tests/cudapy/test_print.py +193 -0
  370. numba_cuda/numba/cuda/tests/cudapy/test_py2_div_issue.py +37 -0
  371. numba_cuda/numba/cuda/tests/cudapy/test_random.py +117 -0
  372. numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +614 -0
  373. numba_cuda/numba/cuda/tests/cudapy/test_recursion.py +130 -0
  374. numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +94 -0
  375. numba_cuda/numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py +83 -0
  376. numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +86 -0
  377. numba_cuda/numba/cuda/tests/cudapy/test_slicing.py +40 -0
  378. numba_cuda/numba/cuda/tests/cudapy/test_sm.py +457 -0
  379. numba_cuda/numba/cuda/tests/cudapy/test_sm_creation.py +233 -0
  380. numba_cuda/numba/cuda/tests/cudapy/test_ssa.py +454 -0
  381. numba_cuda/numba/cuda/tests/cudapy/test_stream_api.py +56 -0
  382. numba_cuda/numba/cuda/tests/cudapy/test_sync.py +277 -0
  383. numba_cuda/numba/cuda/tests/cudapy/test_tracing.py +200 -0
  384. numba_cuda/numba/cuda/tests/cudapy/test_transpose.py +90 -0
  385. numba_cuda/numba/cuda/tests/cudapy/test_typeconv.py +333 -0
  386. numba_cuda/numba/cuda/tests/cudapy/test_typeinfer.py +538 -0
  387. numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +585 -0
  388. numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +42 -0
  389. numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +485 -0
  390. numba_cuda/numba/cuda/tests/cudapy/test_vectorize.py +312 -0
  391. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_complex.py +23 -0
  392. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +183 -0
  393. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_device.py +40 -0
  394. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py +40 -0
  395. numba_cuda/numba/cuda/tests/cudapy/test_warning.py +206 -0
  396. numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +331 -0
  397. numba_cuda/numba/cuda/tests/cudasim/__init__.py +9 -0
  398. numba_cuda/numba/cuda/tests/cudasim/support.py +9 -0
  399. numba_cuda/numba/cuda/tests/cudasim/test_cudasim_issues.py +111 -0
  400. numba_cuda/numba/cuda/tests/data/__init__.py +2 -0
  401. numba_cuda/numba/cuda/tests/data/cta_barrier.cu +28 -0
  402. numba_cuda/numba/cuda/tests/data/cuda_include.cu +10 -0
  403. numba_cuda/numba/cuda/tests/data/error.cu +12 -0
  404. numba_cuda/numba/cuda/tests/data/include/add.cuh +8 -0
  405. numba_cuda/numba/cuda/tests/data/jitlink.cu +28 -0
  406. numba_cuda/numba/cuda/tests/data/jitlink.ptx +49 -0
  407. numba_cuda/numba/cuda/tests/data/warn.cu +12 -0
  408. numba_cuda/numba/cuda/tests/doc_examples/__init__.py +9 -0
  409. numba_cuda/numba/cuda/tests/doc_examples/ffi/__init__.py +2 -0
  410. numba_cuda/numba/cuda/tests/doc_examples/ffi/functions.cu +54 -0
  411. numba_cuda/numba/cuda/tests/doc_examples/ffi/include/mul.cuh +8 -0
  412. numba_cuda/numba/cuda/tests/doc_examples/ffi/saxpy.cu +14 -0
  413. numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +86 -0
  414. numba_cuda/numba/cuda/tests/doc_examples/test_cpointer.py +68 -0
  415. numba_cuda/numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py +81 -0
  416. numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +141 -0
  417. numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +160 -0
  418. numba_cuda/numba/cuda/tests/doc_examples/test_matmul.py +180 -0
  419. numba_cuda/numba/cuda/tests/doc_examples/test_montecarlo.py +119 -0
  420. numba_cuda/numba/cuda/tests/doc_examples/test_random.py +66 -0
  421. numba_cuda/numba/cuda/tests/doc_examples/test_reduction.py +80 -0
  422. numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +206 -0
  423. numba_cuda/numba/cuda/tests/doc_examples/test_ufunc.py +53 -0
  424. numba_cuda/numba/cuda/tests/doc_examples/test_vecadd.py +76 -0
  425. numba_cuda/numba/cuda/tests/nocuda/__init__.py +9 -0
  426. numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +391 -0
  427. numba_cuda/numba/cuda/tests/nocuda/test_function_resolution.py +48 -0
  428. numba_cuda/numba/cuda/tests/nocuda/test_import.py +63 -0
  429. numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +252 -0
  430. numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +59 -0
  431. numba_cuda/numba/cuda/tests/nrt/__init__.py +9 -0
  432. numba_cuda/numba/cuda/tests/nrt/test_nrt.py +387 -0
  433. numba_cuda/numba/cuda/tests/nrt/test_nrt_refct.py +124 -0
  434. numba_cuda/numba/cuda/tests/support.py +900 -0
  435. numba_cuda/numba/cuda/typeconv/__init__.py +4 -0
  436. numba_cuda/numba/cuda/typeconv/castgraph.py +137 -0
  437. numba_cuda/numba/cuda/typeconv/rules.py +63 -0
  438. numba_cuda/numba/cuda/typeconv/typeconv.py +121 -0
  439. numba_cuda/numba/cuda/types/__init__.py +233 -0
  440. numba_cuda/numba/cuda/types/__init__.pyi +167 -0
  441. numba_cuda/numba/cuda/types/abstract.py +9 -0
  442. numba_cuda/numba/cuda/types/common.py +9 -0
  443. numba_cuda/numba/cuda/types/containers.py +9 -0
  444. numba_cuda/numba/cuda/types/cuda_abstract.py +533 -0
  445. numba_cuda/numba/cuda/types/cuda_common.py +110 -0
  446. numba_cuda/numba/cuda/types/cuda_containers.py +971 -0
  447. numba_cuda/numba/cuda/types/cuda_function_type.py +230 -0
  448. numba_cuda/numba/cuda/types/cuda_functions.py +798 -0
  449. numba_cuda/numba/cuda/types/cuda_iterators.py +120 -0
  450. numba_cuda/numba/cuda/types/cuda_misc.py +569 -0
  451. numba_cuda/numba/cuda/types/cuda_npytypes.py +690 -0
  452. numba_cuda/numba/cuda/types/cuda_scalars.py +280 -0
  453. numba_cuda/numba/cuda/types/ext_types.py +101 -0
  454. numba_cuda/numba/cuda/types/function_type.py +11 -0
  455. numba_cuda/numba/cuda/types/functions.py +9 -0
  456. numba_cuda/numba/cuda/types/iterators.py +9 -0
  457. numba_cuda/numba/cuda/types/misc.py +9 -0
  458. numba_cuda/numba/cuda/types/npytypes.py +9 -0
  459. numba_cuda/numba/cuda/types/scalars.py +9 -0
  460. numba_cuda/numba/cuda/typing/__init__.py +19 -0
  461. numba_cuda/numba/cuda/typing/arraydecl.py +939 -0
  462. numba_cuda/numba/cuda/typing/asnumbatype.py +130 -0
  463. numba_cuda/numba/cuda/typing/bufproto.py +70 -0
  464. numba_cuda/numba/cuda/typing/builtins.py +1209 -0
  465. numba_cuda/numba/cuda/typing/cffi_utils.py +219 -0
  466. numba_cuda/numba/cuda/typing/cmathdecl.py +47 -0
  467. numba_cuda/numba/cuda/typing/collections.py +138 -0
  468. numba_cuda/numba/cuda/typing/context.py +782 -0
  469. numba_cuda/numba/cuda/typing/ctypes_utils.py +125 -0
  470. numba_cuda/numba/cuda/typing/dictdecl.py +63 -0
  471. numba_cuda/numba/cuda/typing/enumdecl.py +74 -0
  472. numba_cuda/numba/cuda/typing/listdecl.py +147 -0
  473. numba_cuda/numba/cuda/typing/mathdecl.py +158 -0
  474. numba_cuda/numba/cuda/typing/npdatetime.py +322 -0
  475. numba_cuda/numba/cuda/typing/npydecl.py +749 -0
  476. numba_cuda/numba/cuda/typing/setdecl.py +115 -0
  477. numba_cuda/numba/cuda/typing/templates.py +1446 -0
  478. numba_cuda/numba/cuda/typing/typeof.py +301 -0
  479. numba_cuda/numba/cuda/ufuncs.py +746 -0
  480. numba_cuda/numba/cuda/utils.py +724 -0
  481. numba_cuda/numba/cuda/vector_types.py +214 -0
  482. numba_cuda/numba/cuda/vectorizers.py +260 -0
  483. numba_cuda-0.21.1.dist-info/METADATA +109 -0
  484. numba_cuda-0.21.1.dist-info/RECORD +488 -0
  485. numba_cuda-0.21.1.dist-info/WHEEL +5 -0
  486. numba_cuda-0.21.1.dist-info/licenses/LICENSE +26 -0
  487. numba_cuda-0.21.1.dist-info/licenses/LICENSE.numba +24 -0
  488. numba_cuda-0.21.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,900 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: BSD-2-Clause
3
+
4
+ import cmath
5
+ import concurrent.futures
6
+ import contextlib
7
+ import enum
8
+ import gc
9
+ import math
10
+ import unittest
11
+ import os
12
+ import io
13
+ import subprocess
14
+ import sys
15
+ import shutil
16
+ import warnings
17
+ import tempfile
18
+ import time
19
+ import types as pytypes
20
+ from functools import cached_property
21
+ import multiprocessing as mp
22
+ import traceback
23
+
24
+ import numpy as np
25
+
26
+ from numba.cuda import types
27
+ from numba.cuda.core import errors
28
+ from numba.cuda.core import config
29
+ from numba.cuda.typing import cffi_utils
30
+ from numba.cuda.memory_management.nrt import rtsys
31
+ from numba.cuda.extending import (
32
+ typeof_impl,
33
+ register_model,
34
+ NativeValue,
35
+ )
36
+ from numba.cuda.core.pythonapi import unbox
37
+ from numba.cuda.datamodel.models import OpaqueModel
38
+ from numba.cuda.np import numpy_support
39
+
40
+ from numba.cuda import HAS_NUMBA
41
+
42
+ if HAS_NUMBA:
43
+ from numba.core.extending import (
44
+ typeof_impl as upstream_typeof_impl,
45
+ )
46
+ from numba.core import types as upstream_types
47
+
48
+
49
+ class EnableNRTStatsMixin(object):
50
+ """Mixin to enable the NRT statistics counters."""
51
+
52
+ def setUp(self):
53
+ rtsys.memsys_enable_stats()
54
+
55
+ def tearDown(self):
56
+ rtsys.memsys_disable_stats()
57
+
58
+
59
+ skip_unless_cffi = unittest.skipUnless(cffi_utils.SUPPORTED, "requires cffi")
60
+
61
+ _lnx_reason = "linux only test"
62
+ linux_only = unittest.skipIf(not sys.platform.startswith("linux"), _lnx_reason)
63
+
64
+ _win_reason = "Windows only test"
65
+ windows_only = unittest.skipIf(not sys.platform.startswith("win"), _win_reason)
66
+
67
+ IS_NUMPY_2 = numpy_support.numpy_version >= (2, 0)
68
+ skip_if_numpy_2 = unittest.skipIf(IS_NUMPY_2, "Not supported on numpy 2.0+")
69
+
70
+ # Typeguard
71
+ has_typeguard = bool(os.environ.get("NUMBA_USE_TYPEGUARD", 0))
72
+
73
+ skip_unless_typeguard = unittest.skipUnless(
74
+ has_typeguard,
75
+ "Typeguard is not enabled",
76
+ )
77
+
78
+ skip_if_typeguard = unittest.skipIf(
79
+ has_typeguard,
80
+ "Broken if Typeguard is enabled",
81
+ )
82
+
83
+ _trashcan_dir = "numba-cuda-tests"
84
+
85
+ if os.name == "nt":
86
+ # Under Windows, gettempdir() points to the user-local temp dir
87
+ _trashcan_dir = os.path.join(tempfile.gettempdir(), _trashcan_dir)
88
+ else:
89
+ # Mix the UID into the directory name to allow different users to
90
+ # run the test suite without permission errors (issue #1586)
91
+ _trashcan_dir = os.path.join(
92
+ tempfile.gettempdir(), "%s.%s" % (_trashcan_dir, os.getuid())
93
+ )
94
+
95
+ # Stale temporary directories are deleted after they are older than this value.
96
+ # The test suite probably won't ever take longer than this...
97
+ _trashcan_timeout = 24 * 3600 # 1 day
98
+
99
+
100
+ def _create_trashcan_dir():
101
+ try:
102
+ os.mkdir(_trashcan_dir)
103
+ except FileExistsError:
104
+ pass
105
+
106
+
107
+ def _purge_trashcan_dir():
108
+ freshness_threshold = time.time() - _trashcan_timeout
109
+ for fn in sorted(os.listdir(_trashcan_dir)):
110
+ fn = os.path.join(_trashcan_dir, fn)
111
+ try:
112
+ st = os.stat(fn)
113
+ if st.st_mtime < freshness_threshold:
114
+ shutil.rmtree(fn, ignore_errors=True)
115
+ except OSError:
116
+ # In parallel testing, several processes can attempt to
117
+ # remove the same entry at once, ignore.
118
+ pass
119
+
120
+
121
+ def _create_trashcan_subdir(prefix):
122
+ _purge_trashcan_dir()
123
+ path = tempfile.mkdtemp(prefix=prefix + "-", dir=_trashcan_dir)
124
+ return path
125
+
126
+
127
+ def temp_directory(prefix):
128
+ """
129
+ Create a temporary directory with the given *prefix* that will survive
130
+ at least as long as this process invocation. The temporary directory
131
+ will be eventually deleted when it becomes stale enough.
132
+
133
+ This is necessary because a DLL file can't be deleted while in use
134
+ under Windows.
135
+
136
+ An interesting side-effect is to be able to inspect the test files
137
+ shortly after a test suite run.
138
+ """
139
+ _create_trashcan_dir()
140
+ return _create_trashcan_subdir(prefix)
141
+
142
+
143
+ def import_dynamic(modname):
144
+ """
145
+ Import and return a module of the given name. Care is taken to
146
+ avoid issues due to Python's internal directory caching.
147
+ """
148
+ import importlib
149
+
150
+ importlib.invalidate_caches()
151
+ __import__(modname)
152
+ return sys.modules[modname]
153
+
154
+
155
+ def ignore_internal_warnings():
156
+ """Use in testing within a ` warnings.catch_warnings` block to filter out
157
+ warnings that are unrelated/internally generated by Numba.
158
+ """
159
+ # Filter out warnings from typeguard
160
+ warnings.filterwarnings("ignore", module="typeguard")
161
+ # Filter out warnings about TBB interface mismatch
162
+ warnings.filterwarnings(
163
+ action="ignore",
164
+ message=r".*TBB_INTERFACE_VERSION.*",
165
+ category=errors.NumbaWarning,
166
+ module=r"numba\.np\.ufunc\.parallel.*",
167
+ )
168
+
169
+
170
+ @contextlib.contextmanager
171
+ def override_config(name, value):
172
+ """
173
+ Return a context manager that temporarily sets Numba config variable
174
+ *name* to *value*. *name* must be the name of an existing variable
175
+ in numba.config.
176
+ """
177
+ old_value = getattr(config, name)
178
+ setattr(config, name, value)
179
+ try:
180
+ yield
181
+ finally:
182
+ setattr(config, name, old_value)
183
+
184
+
185
+ def run_in_subprocess(code, flags=None, env=None, timeout=30):
186
+ """Run a snippet of Python code in a subprocess with flags, if any are
187
+ given. 'env' is passed to subprocess.Popen(). 'timeout' is passed to
188
+ popen.communicate().
189
+
190
+ Returns the stdout and stderr of the subprocess after its termination.
191
+ """
192
+ if flags is None:
193
+ flags = []
194
+ cmd = (
195
+ [
196
+ sys.executable,
197
+ ]
198
+ + flags
199
+ + ["-c", code]
200
+ )
201
+ popen = subprocess.Popen(
202
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env
203
+ )
204
+ out, err = popen.communicate(timeout=timeout)
205
+ if popen.returncode != 0:
206
+ msg = "process failed with code %s: stderr follows\n%s\n"
207
+ raise AssertionError(msg % (popen.returncode, err.decode()))
208
+ return out, err
209
+
210
+
211
+ def captured_stdout():
212
+ """Capture the output of sys.stdout:
213
+
214
+ with captured_stdout() as stdout:
215
+ print("hello")
216
+ self.assertEqual(stdout.getvalue(), "hello\n")
217
+ """
218
+ return contextlib.redirect_stdout(io.StringIO())
219
+
220
+
221
+ def captured_stderr():
222
+ """Capture the output of sys.stderr:
223
+
224
+ with captured_stderr() as stderr:
225
+ print("hello", file=sys.stderr)
226
+ self.assertEqual(stderr.getvalue(), "hello\n")
227
+ """
228
+ return contextlib.redirect_stderr(io.StringIO())
229
+
230
+
231
+ class TestCase(unittest.TestCase):
232
+ longMessage = True
233
+
234
+ # A random state yielding the same random numbers for any test case.
235
+ # Use as `self.random.<method name>`
236
+ @cached_property
237
+ def random(self):
238
+ return np.random.RandomState(42)
239
+
240
+ def reset_module_warnings(self, module):
241
+ """
242
+ Reset the warnings registry of a module. This can be necessary
243
+ as the warnings module is buggy in that regard.
244
+ See http://bugs.python.org/issue4180
245
+ """
246
+ if isinstance(module, str):
247
+ module = sys.modules[module]
248
+ try:
249
+ del module.__warningregistry__
250
+ except AttributeError:
251
+ pass
252
+
253
+ @contextlib.contextmanager
254
+ def assertTypingError(self):
255
+ """
256
+ A context manager that asserts the enclosed code block fails
257
+ compiling in nopython mode.
258
+ """
259
+ _accepted_errors = (
260
+ errors.LoweringError,
261
+ errors.TypingError,
262
+ TypeError,
263
+ NotImplementedError,
264
+ )
265
+ with self.assertRaises(_accepted_errors) as cm:
266
+ yield cm
267
+
268
+ @contextlib.contextmanager
269
+ def assertRefCount(self, *objects):
270
+ """
271
+ A context manager that asserts the given objects have the
272
+ same reference counts before and after executing the
273
+ enclosed block.
274
+ """
275
+ old_refcounts = [sys.getrefcount(x) for x in objects]
276
+ yield
277
+ gc.collect()
278
+ new_refcounts = [sys.getrefcount(x) for x in objects]
279
+ for old, new, obj in zip(old_refcounts, new_refcounts, objects):
280
+ if old != new:
281
+ self.fail(
282
+ "Refcount changed from %d to %d for object: %r"
283
+ % (old, new, obj)
284
+ )
285
+
286
+ def assertRefCountEqual(self, *objects):
287
+ gc.collect()
288
+ rc = [sys.getrefcount(x) for x in objects]
289
+ rc_0 = rc[0]
290
+ for i in range(len(objects))[1:]:
291
+ rc_i = rc[i]
292
+ if rc_0 != rc_i:
293
+ self.fail(
294
+ f"Refcount for objects does not match. "
295
+ f"#0({rc_0}) != #{i}({rc_i}) does not match."
296
+ )
297
+
298
+ @contextlib.contextmanager
299
+ def assertNoNRTLeak(self):
300
+ """
301
+ A context manager that asserts no NRT leak was created during
302
+ the execution of the enclosed block.
303
+ """
304
+ old = rtsys.get_allocation_stats()
305
+ yield
306
+ new = rtsys.get_allocation_stats()
307
+ total_alloc = new.alloc - old.alloc
308
+ total_free = new.free - old.free
309
+ total_mi_alloc = new.mi_alloc - old.mi_alloc
310
+ total_mi_free = new.mi_free - old.mi_free
311
+ self.assertEqual(
312
+ total_alloc,
313
+ total_free,
314
+ "number of data allocs != number of data frees",
315
+ )
316
+ self.assertEqual(
317
+ total_mi_alloc,
318
+ total_mi_free,
319
+ "number of meminfo allocs != number of meminfo frees",
320
+ )
321
+
322
+ _bool_types = (bool, np.bool_)
323
+ _exact_typesets = [
324
+ _bool_types,
325
+ (int,),
326
+ (str,),
327
+ (np.integer,),
328
+ (bytes, np.bytes_),
329
+ ]
330
+ _approx_typesets = [(float,), (complex,), (np.inexact)]
331
+ _sequence_typesets = [(tuple, list)]
332
+ _float_types = (float, np.floating)
333
+ _complex_types = (complex, np.complexfloating)
334
+
335
+ def _detect_family(self, numeric_object):
336
+ """
337
+ This function returns a string description of the type family
338
+ that the object in question belongs to. Possible return values
339
+ are: "exact", "complex", "approximate", "sequence", and "unknown"
340
+ """
341
+ if isinstance(numeric_object, np.ndarray):
342
+ return "ndarray"
343
+
344
+ if isinstance(numeric_object, enum.Enum):
345
+ return "enum"
346
+
347
+ for tp in self._sequence_typesets:
348
+ if isinstance(numeric_object, tp):
349
+ return "sequence"
350
+
351
+ for tp in self._exact_typesets:
352
+ if isinstance(numeric_object, tp):
353
+ return "exact"
354
+
355
+ for tp in self._complex_types:
356
+ if isinstance(numeric_object, tp):
357
+ return "complex"
358
+
359
+ for tp in self._approx_typesets:
360
+ if isinstance(numeric_object, tp):
361
+ return "approximate"
362
+
363
+ return "unknown"
364
+
365
+ def _fix_dtype(self, dtype):
366
+ """
367
+ Fix the given *dtype* for comparison.
368
+ """
369
+ # Under 64-bit Windows, Numpy may return either int32 or int64
370
+ # arrays depending on the function.
371
+ if (
372
+ sys.platform == "win32"
373
+ and sys.maxsize > 2**32
374
+ and dtype == np.dtype("int32")
375
+ ):
376
+ return np.dtype("int64")
377
+ else:
378
+ return dtype
379
+
380
+ def _fix_strides(self, arr):
381
+ """
382
+ Return the strides of the given array, fixed for comparison.
383
+ Strides for 0- or 1-sized dimensions are ignored.
384
+ """
385
+ if arr.size == 0:
386
+ return [0] * arr.ndim
387
+ else:
388
+ return [
389
+ stride / arr.itemsize
390
+ for (stride, shape) in zip(arr.strides, arr.shape)
391
+ if shape > 1
392
+ ]
393
+
394
+ def assertStridesEqual(self, first, second):
395
+ """
396
+ Test that two arrays have the same shape and strides.
397
+ """
398
+ self.assertEqual(first.shape, second.shape, "shapes differ")
399
+ self.assertEqual(first.itemsize, second.itemsize, "itemsizes differ")
400
+ self.assertEqual(
401
+ self._fix_strides(first),
402
+ self._fix_strides(second),
403
+ "strides differ",
404
+ )
405
+
406
+ def assertPreciseEqual(
407
+ self,
408
+ first,
409
+ second,
410
+ prec="exact",
411
+ ulps=1,
412
+ msg=None,
413
+ ignore_sign_on_zero=False,
414
+ abs_tol=None,
415
+ ):
416
+ """
417
+ Versatile equality testing function with more built-in checks than
418
+ standard assertEqual().
419
+
420
+ For arrays, test that layout, dtype, shape are identical, and
421
+ recursively call assertPreciseEqual() on the contents.
422
+
423
+ For other sequences, recursively call assertPreciseEqual() on
424
+ the contents.
425
+
426
+ For scalars, test that two scalars or have similar types and are
427
+ equal up to a computed precision.
428
+ If the scalars are instances of exact types or if *prec* is
429
+ 'exact', they are compared exactly.
430
+ If the scalars are instances of inexact types (float, complex)
431
+ and *prec* is not 'exact', then the number of significant bits
432
+ is computed according to the value of *prec*: 53 bits if *prec*
433
+ is 'double', 24 bits if *prec* is single. This number of bits
434
+ can be lowered by raising the *ulps* value.
435
+ ignore_sign_on_zero can be set to True if zeros are to be considered
436
+ equal regardless of their sign bit.
437
+ abs_tol if this is set to a float value its value is used in the
438
+ following. If, however, this is set to the string "eps" then machine
439
+ precision of the type(first) is used in the following instead. This
440
+ kwarg is used to check if the absolute difference in value between first
441
+ and second is less than the value set, if so the numbers being compared
442
+ are considered equal. (This is to handle small numbers typically of
443
+ magnitude less than machine precision).
444
+
445
+ Any value of *prec* other than 'exact', 'single' or 'double'
446
+ will raise an error.
447
+ """
448
+ try:
449
+ self._assertPreciseEqual(
450
+ first, second, prec, ulps, msg, ignore_sign_on_zero, abs_tol
451
+ )
452
+ except AssertionError as exc:
453
+ failure_msg = str(exc)
454
+ # Fall off of the 'except' scope to avoid Python 3 exception
455
+ # chaining.
456
+ else:
457
+ return
458
+ # Decorate the failure message with more information
459
+ self.fail("when comparing %s and %s: %s" % (first, second, failure_msg))
460
+
461
+ def _assertPreciseEqual(
462
+ self,
463
+ first,
464
+ second,
465
+ prec="exact",
466
+ ulps=1,
467
+ msg=None,
468
+ ignore_sign_on_zero=False,
469
+ abs_tol=None,
470
+ ):
471
+ """Recursive workhorse for assertPreciseEqual()."""
472
+
473
+ def _assertNumberEqual(first, second, delta=None):
474
+ if (
475
+ delta is None
476
+ or first == second == 0.0
477
+ or math.isinf(first)
478
+ or math.isinf(second)
479
+ ):
480
+ self.assertEqual(first, second, msg=msg)
481
+ # For signed zeros
482
+ if not ignore_sign_on_zero:
483
+ try:
484
+ if math.copysign(1, first) != math.copysign(1, second):
485
+ self.fail(
486
+ self._formatMessage(
487
+ msg, "%s != %s" % (first, second)
488
+ )
489
+ )
490
+ except TypeError:
491
+ pass
492
+ else:
493
+ self.assertAlmostEqual(first, second, delta=delta, msg=msg)
494
+
495
+ first_family = self._detect_family(first)
496
+ second_family = self._detect_family(second)
497
+
498
+ assertion_message = "Type Family mismatch. (%s != %s)" % (
499
+ first_family,
500
+ second_family,
501
+ )
502
+ if msg:
503
+ assertion_message += ": %s" % (msg,)
504
+ self.assertEqual(first_family, second_family, msg=assertion_message)
505
+
506
+ # We now know they are in the same comparison family
507
+ compare_family = first_family
508
+
509
+ # For recognized sequences, recurse
510
+ if compare_family == "ndarray":
511
+ dtype = self._fix_dtype(first.dtype)
512
+ self.assertEqual(dtype, self._fix_dtype(second.dtype))
513
+ self.assertEqual(
514
+ first.ndim, second.ndim, "different number of dimensions"
515
+ )
516
+ self.assertEqual(first.shape, second.shape, "different shapes")
517
+ self.assertEqual(
518
+ first.flags.writeable,
519
+ second.flags.writeable,
520
+ "different mutability",
521
+ )
522
+ # itemsize is already checked by the dtype test above
523
+ self.assertEqual(
524
+ self._fix_strides(first),
525
+ self._fix_strides(second),
526
+ "different strides",
527
+ )
528
+ if first.dtype != dtype:
529
+ first = first.astype(dtype)
530
+ if second.dtype != dtype:
531
+ second = second.astype(dtype)
532
+ for a, b in zip(first.flat, second.flat):
533
+ self._assertPreciseEqual(
534
+ a, b, prec, ulps, msg, ignore_sign_on_zero, abs_tol
535
+ )
536
+ return
537
+
538
+ elif compare_family == "sequence":
539
+ self.assertEqual(len(first), len(second), msg=msg)
540
+ for a, b in zip(first, second):
541
+ self._assertPreciseEqual(
542
+ a, b, prec, ulps, msg, ignore_sign_on_zero, abs_tol
543
+ )
544
+ return
545
+
546
+ elif compare_family == "exact":
547
+ exact_comparison = True
548
+
549
+ elif compare_family in ["complex", "approximate"]:
550
+ exact_comparison = False
551
+
552
+ elif compare_family == "enum":
553
+ self.assertIs(first.__class__, second.__class__)
554
+ self._assertPreciseEqual(
555
+ first.value,
556
+ second.value,
557
+ prec,
558
+ ulps,
559
+ msg,
560
+ ignore_sign_on_zero,
561
+ abs_tol,
562
+ )
563
+ return
564
+
565
+ elif compare_family == "unknown":
566
+ # Assume these are non-numeric types: we will fall back
567
+ # on regular unittest comparison.
568
+ self.assertIs(first.__class__, second.__class__)
569
+ exact_comparison = True
570
+
571
+ else:
572
+ assert 0, "unexpected family"
573
+
574
+ # If a Numpy scalar, check the dtype is exactly the same too
575
+ # (required for datetime64 and timedelta64).
576
+ if hasattr(first, "dtype") and hasattr(second, "dtype"):
577
+ self.assertEqual(first.dtype, second.dtype)
578
+
579
+ # Mixing bools and non-bools should always fail
580
+ if isinstance(first, self._bool_types) != isinstance(
581
+ second, self._bool_types
582
+ ):
583
+ assertion_message = "Mismatching return types (%s vs. %s)" % (
584
+ first.__class__,
585
+ second.__class__,
586
+ )
587
+ if msg:
588
+ assertion_message += ": %s" % (msg,)
589
+ self.fail(assertion_message)
590
+
591
+ try:
592
+ if cmath.isnan(first) and cmath.isnan(second):
593
+ # The NaNs will compare unequal, skip regular comparison
594
+ return
595
+ except TypeError:
596
+ # Not floats.
597
+ pass
598
+
599
+ # if absolute comparison is set, use it
600
+ if abs_tol is not None:
601
+ if abs_tol == "eps":
602
+ rtol = np.finfo(type(first)).eps
603
+ elif isinstance(abs_tol, float):
604
+ rtol = abs_tol
605
+ else:
606
+ raise ValueError(
607
+ 'abs_tol is not "eps" or a float, found %s' % abs_tol
608
+ )
609
+ if abs(first - second) < rtol:
610
+ return
611
+
612
+ exact_comparison = exact_comparison or prec == "exact"
613
+
614
+ if not exact_comparison and prec != "exact":
615
+ if prec == "single":
616
+ bits = 24
617
+ elif prec == "double":
618
+ bits = 53
619
+ else:
620
+ raise ValueError("unsupported precision %r" % (prec,))
621
+ k = 2 ** (ulps - bits - 1)
622
+ delta = k * (abs(first) + abs(second))
623
+ else:
624
+ delta = None
625
+ if isinstance(first, self._complex_types):
626
+ _assertNumberEqual(first.real, second.real, delta)
627
+ _assertNumberEqual(first.imag, second.imag, delta)
628
+ elif isinstance(first, (np.timedelta64, np.datetime64)):
629
+ # Since Np 1.16 NaT == NaT is False, so special comparison needed
630
+ if np.isnat(first):
631
+ self.assertEqual(np.isnat(first), np.isnat(second))
632
+ else:
633
+ _assertNumberEqual(first, second, delta)
634
+ else:
635
+ _assertNumberEqual(first, second, delta)
636
+
637
+ def subprocess_test_runner(
638
+ self,
639
+ test_module,
640
+ test_class=None,
641
+ test_name=None,
642
+ envvars=None,
643
+ timeout=60,
644
+ flags=None,
645
+ _subproc_test_env="1",
646
+ ):
647
+ """
648
+ Runs named unit test(s) as specified in the arguments as:
649
+ test_module.test_class.test_name. test_module must always be supplied
650
+ and if no further refinement is made with test_class and test_name then
651
+ all tests in the module will be run. The tests will be run in a
652
+ subprocess with environment variables specified in `envvars`.
653
+ If given, envvars must be a map of form:
654
+ environment variable name (str) -> value (str)
655
+ If given, flags must be a map of form:
656
+ flag including the `-` (str) -> value (str)
657
+ It is most convenient to use this method in conjunction with
658
+ @needs_subprocess as the decorator will cause the decorated test to be
659
+ skipped unless the `SUBPROC_TEST` environment variable is set to
660
+ the same value of ``_subproc_test_env``
661
+ (this special environment variable is set by this method such that the
662
+ specified test(s) will not be skipped in the subprocess).
663
+
664
+
665
+ Following execution in the subprocess this method will check the test(s)
666
+ executed without error. The timeout kwarg can be used to allow more time
667
+ for longer running tests, it defaults to 60 seconds.
668
+ """
669
+ parts = (test_module, test_class, test_name)
670
+ fully_qualified_test = ".".join(x for x in parts if x is not None)
671
+ flags_args = []
672
+ if flags is not None:
673
+ for flag, value in flags.items():
674
+ flags_args.append(f"{flag}")
675
+ flags_args.append(f"{value}")
676
+ cmd = [
677
+ sys.executable,
678
+ *flags_args,
679
+ "-m",
680
+ "numba.runtests",
681
+ fully_qualified_test,
682
+ ]
683
+ env_copy = os.environ.copy()
684
+ env_copy["SUBPROC_TEST"] = _subproc_test_env
685
+ try:
686
+ env_copy["COVERAGE_PROCESS_START"] = os.environ["COVERAGE_RCFILE"]
687
+ except KeyError:
688
+ pass # ignored
689
+ envvars = pytypes.MappingProxyType({} if envvars is None else envvars)
690
+ env_copy.update(envvars)
691
+ status = subprocess.run(
692
+ cmd,
693
+ stdout=subprocess.PIPE,
694
+ stderr=subprocess.PIPE,
695
+ timeout=timeout,
696
+ env=env_copy,
697
+ universal_newlines=True,
698
+ )
699
+ streams = (
700
+ f"\ncaptured stdout: {status.stdout}\n"
701
+ f"captured stderr: {status.stderr}"
702
+ )
703
+ self.assertEqual(status.returncode, 0, streams)
704
+ # Python 3.12.1 report
705
+ no_tests_ran = "NO TESTS RAN"
706
+ if no_tests_ran in status.stderr:
707
+ self.skipTest(no_tests_ran)
708
+ else:
709
+ self.assertIn("OK", status.stderr)
710
+ return status
711
+
712
+ def run_test_in_subprocess(maybefunc=None, timeout=60, envvars=None):
713
+ """Runs the decorated test in a subprocess via invoking numba's test
714
+ runner. kwargs timeout and envvars are passed through to
715
+ subprocess_test_runner."""
716
+
717
+ def wrapper(func):
718
+ def inner(self, *args, **kwargs):
719
+ if os.environ.get("SUBPROC_TEST", None) != func.__name__:
720
+ # Not in a subprocess test env, so stage the call to run the
721
+ # test in a subprocess which will set the env var.
722
+ class_name = self.__class__.__name__
723
+ self.subprocess_test_runner(
724
+ test_module=self.__module__,
725
+ test_class=class_name,
726
+ test_name=func.__name__,
727
+ timeout=timeout,
728
+ envvars=envvars,
729
+ _subproc_test_env=func.__name__,
730
+ )
731
+ else:
732
+ # env var is set, so we're in the subprocess, run the
733
+ # actual test.
734
+ func(self)
735
+
736
+ return inner
737
+
738
+ if isinstance(maybefunc, pytypes.FunctionType):
739
+ return wrapper(maybefunc)
740
+ else:
741
+ return wrapper
742
+
743
+ def make_dummy_type(self):
744
+ """Use to generate a dummy type unique to this test. Returns a python
745
+ Dummy class and a corresponding Numba type DummyType."""
746
+
747
+ # Use test_id to make sure no collision is possible.
748
+ test_id = self.id()
749
+ DummyType = type("DummyTypeFor{}".format(test_id), (types.Opaque,), {})
750
+
751
+ dummy_type = DummyType("my_dummy")
752
+ register_model(DummyType)(OpaqueModel)
753
+
754
+ class Dummy(object):
755
+ pass
756
+
757
+ @typeof_impl.register(Dummy)
758
+ def typeof_dummy(val, c):
759
+ return dummy_type
760
+
761
+ # Dual registration for cross-target tests
762
+ if HAS_NUMBA:
763
+ UpstreamDummyType = type(
764
+ "DummyTypeFor{}".format(test_id), (upstream_types.Opaque,), {}
765
+ )
766
+ upstream_dummy_type = UpstreamDummyType("my_dummy")
767
+
768
+ @upstream_typeof_impl.register(Dummy)
769
+ def typeof_dummy_core(val, c):
770
+ return upstream_dummy_type
771
+
772
+ @unbox(DummyType)
773
+ def unbox_dummy(typ, obj, c):
774
+ return NativeValue(c.context.get_dummy_value())
775
+
776
+ return Dummy, DummyType
777
+
778
+
779
+ class MemoryLeak(object):
780
+ __enable_leak_check = True
781
+
782
+ def memory_leak_setup(self):
783
+ # Clean up any NRT-backed objects hanging in a dead reference cycle
784
+ gc.collect()
785
+ self.__init_stats = rtsys.get_allocation_stats()
786
+
787
+ def memory_leak_teardown(self):
788
+ if self.__enable_leak_check:
789
+ self.assert_no_memory_leak()
790
+
791
+ def assert_no_memory_leak(self):
792
+ old = self.__init_stats
793
+ new = rtsys.get_allocation_stats()
794
+ total_alloc = new.alloc - old.alloc
795
+ total_free = new.free - old.free
796
+ total_mi_alloc = new.mi_alloc - old.mi_alloc
797
+ total_mi_free = new.mi_free - old.mi_free
798
+ self.assertEqual(total_alloc, total_free)
799
+ self.assertEqual(total_mi_alloc, total_mi_free)
800
+
801
+ def disable_leak_check(self):
802
+ # For per-test use when MemoryLeakMixin is injected into a TestCase
803
+ self.__enable_leak_check = False
804
+
805
+
806
+ class MemoryLeakMixin(EnableNRTStatsMixin, MemoryLeak):
807
+ def setUp(self):
808
+ super(MemoryLeakMixin, self).setUp()
809
+ self.memory_leak_setup()
810
+
811
+ def tearDown(self):
812
+ gc.collect()
813
+ self.memory_leak_teardown()
814
+ super(MemoryLeakMixin, self).tearDown()
815
+
816
+
817
+ class CheckWarningsMixin(object):
818
+ @contextlib.contextmanager
819
+ def check_warnings(self, messages, category=RuntimeWarning):
820
+ with warnings.catch_warnings(record=True) as catch:
821
+ warnings.simplefilter("always")
822
+ yield
823
+ found = 0
824
+ for w in catch:
825
+ for m in messages:
826
+ if m in str(w.message):
827
+ self.assertEqual(w.category, category)
828
+ found += 1
829
+ self.assertEqual(found, len(messages))
830
+
831
+
832
+ @contextlib.contextmanager
833
+ def override_env_config(name, value):
834
+ """
835
+ Return a context manager that temporarily sets an Numba config environment
836
+ *name* to *value*.
837
+ """
838
+ old = os.environ.get(name)
839
+ os.environ[name] = value
840
+ config.reload_config()
841
+
842
+ try:
843
+ yield
844
+ finally:
845
+ if old is None:
846
+ # If it wasn't set originally, delete the environ var
847
+ del os.environ[name]
848
+ else:
849
+ # Otherwise, restore to the old value
850
+ os.environ[name] = old
851
+ # Always reload config
852
+ config.reload_config()
853
+
854
+
855
+ def run_in_new_process_in_cache_dir(func, cache_dir, verbose=True):
856
+ """Spawn a new process to run `func` with a temporary cache directory.
857
+
858
+ The childprocess's stdout and stderr will be captured and redirected to
859
+ the current process's stdout and stderr.
860
+
861
+ Similar to ``run_in_new_process_caching()`` but the ``cache_dir`` is a
862
+ directory path instead of a name prefix for the directory path.
863
+
864
+ Returns
865
+ -------
866
+ ret : dict
867
+ exitcode: 0 for success. 1 for exception-raised.
868
+ stdout: str
869
+ stderr: str
870
+ """
871
+ with override_env_config("NUMBA_CACHE_DIR", cache_dir):
872
+ with concurrent.futures.ProcessPoolExecutor(
873
+ mp_context=mp.get_context("spawn")
874
+ ) as exe:
875
+ future = exe.submit(_remote_runner, func)
876
+
877
+ stdout, stderr, exitcode = future.result()
878
+ if verbose:
879
+ if stdout:
880
+ print()
881
+ print("STDOUT".center(80, "-"))
882
+ print(stdout)
883
+ if stderr:
884
+ print(file=sys.stderr)
885
+ print("STDERR".center(80, "-"), file=sys.stderr)
886
+ print(stderr, file=sys.stderr)
887
+ return {"exitcode": exitcode, "stdout": stdout, "stderr": stderr}
888
+
889
+
890
+ def _remote_runner(fn, qout):
891
+ """Used by `run_in_new_process_caching()`"""
892
+ with captured_stderr() as stderr, captured_stdout() as stdout:
893
+ try:
894
+ fn()
895
+ except Exception:
896
+ traceback.print_exc(file=sys.stderr)
897
+ exitcode = 1
898
+ else:
899
+ exitcode = 0
900
+ return stdout.getvalue().strip(), stderr.getvalue().strip(), exitcode