Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b0dfc75

Browse files
authored
bpo-41773: Raise exception for non-finite weights in random.choices(). (GH-22441)
1 parent e8acc35 commit b0dfc75

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

Doc/library/random.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ Functions for sequences
180180

181181
The *weights* or *cum_weights* can use any numeric type that interoperates
182182
with the :class:`float` values returned by :func:`random` (that includes
183-
integers, floats, and fractions but excludes decimals). Behavior is
184-
undefined if any weight is negative. A :exc:`ValueError` is raised if all
183+
integers, floats, and fractions but excludes decimals). Weights are assumed
184+
to be non-negative and finite. A :exc:`ValueError` is raised if all
185185
weights are zero.
186186

187187
For a given seed, the :func:`choices` function with equal weighting

Lib/random.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
from warnings import warn as _warn
4949
from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
5050
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
51-
from math import tau as TWOPI, floor as _floor
51+
from math import tau as TWOPI, floor as _floor, isfinite as _isfinite
5252
from os import urandom as _urandom
5353
from _collections_abc import Set as _Set, Sequence as _Sequence
5454
from itertools import accumulate as _accumulate, repeat as _repeat
@@ -492,6 +492,8 @@ def choices(self, population, weights=None, *, cum_weights=None, k=1):
492492
total = cum_weights[-1] + 0.0 # convert to float
493493
if total <= 0.0:
494494
raise ValueError('Total of weights must be greater than zero')
495+
if not _isfinite(total):
496+
raise ValueError('Total of weights must be finite')
495497
bisect = _bisect
496498
hi = n - 1
497499
return [population[bisect(cum_weights, random() * total, 0, hi)]

Lib/test/test_random.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,22 @@ def test_choices_with_all_zero_weights(self):
324324
with self.assertRaises(ValueError):
325325
self.gen.choices('AB', [0.0, 0.0])
326326

327+
def test_choices_negative_total(self):
328+
with self.assertRaises(ValueError):
329+
self.gen.choices('ABC', [3, -5, 1])
330+
331+
def test_choices_infinite_total(self):
332+
with self.assertRaises(ValueError):
333+
self.gen.choices('A', [float('inf')])
334+
with self.assertRaises(ValueError):
335+
self.gen.choices('AB', [0.0, float('inf')])
336+
with self.assertRaises(ValueError):
337+
self.gen.choices('AB', [-float('inf'), 123])
338+
with self.assertRaises(ValueError):
339+
self.gen.choices('AB', [0.0, float('nan')])
340+
with self.assertRaises(ValueError):
341+
self.gen.choices('AB', [float('-inf'), float('inf')])
342+
327343
def test_gauss(self):
328344
# Ensure that the seed() method initializes all the hidden state. In
329345
# particular, through 2.2.1 it failed to reset a piece of state used
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Note in documentation that :func:`random.choices` doesn't support non-finite
2+
weights, raise :exc:`ValueError` when given non-finite weights.

0 commit comments

Comments
 (0)