@@ -3005,6 +3005,45 @@ def test_reduce_casterrors(offset):
3005
3005
assert out [()] < value * offset
3006
3006
3007
3007
3008
+ @pytest .mark .skipif (not HAS_REFCOUNT , reason = "Python lacks refcounts" )
3009
+ def test_reduction_no_reference_leak ():
3010
+ # Test that the generic reduction does not leak references.
3011
+ # gh-29358
3012
+ arr = np .array ([1 , 2 , 3 ], dtype = np .int32 )
3013
+ count = sys .getrefcount (arr )
3014
+
3015
+ np .add .reduce (arr , dtype = np .int32 , initial = 0 )
3016
+ assert count == sys .getrefcount (arr )
3017
+
3018
+ np .add .accumulate (arr , dtype = np .int32 )
3019
+ assert count == sys .getrefcount (arr )
3020
+
3021
+ np .add .reduceat (arr , [0 , 1 ], dtype = np .int32 )
3022
+ assert count == sys .getrefcount (arr )
3023
+
3024
+ # with `out=` the reference count is not changed
3025
+ out = np .empty ((), dtype = np .int32 )
3026
+ out_count = sys .getrefcount (out )
3027
+
3028
+ np .add .reduce (arr , dtype = np .int32 , out = out , initial = 0 )
3029
+ assert count == sys .getrefcount (arr )
3030
+ assert out_count == sys .getrefcount (out )
3031
+
3032
+ out = np .empty (arr .shape , dtype = np .int32 )
3033
+ out_count = sys .getrefcount (out )
3034
+
3035
+ np .add .accumulate (arr , dtype = np .int32 , out = out )
3036
+ assert count == sys .getrefcount (arr )
3037
+ assert out_count == sys .getrefcount (out )
3038
+
3039
+ out = np .empty ((2 ,), dtype = np .int32 )
3040
+ out_count = sys .getrefcount (out )
3041
+
3042
+ np .add .reduceat (arr , [0 , 1 ], dtype = np .int32 , out = out )
3043
+ assert count == sys .getrefcount (arr )
3044
+ assert out_count == sys .getrefcount (out )
3045
+
3046
+
3008
3047
def test_object_reduce_cleanup_on_failure ():
3009
3048
# Test cleanup, including of the initial value (manually provided or not)
3010
3049
with pytest .raises (TypeError ):
0 commit comments