diff --git a/faker/providers/python/__init__.py b/faker/providers/python/__init__.py index 3f470e07b5..1febbeac82 100644 --- a/faker/providers/python/__init__.py +++ b/faker/providers/python/__init__.py @@ -66,9 +66,9 @@ def pyfloat(self, left_digits=None, right_digits=None, positive=False, raise ValueError('Min value cannot be greater than max value') if None not in (min_value, max_value) and min_value == max_value: raise ValueError('Min and max value cannot be the same') - if positive and min_value is not None and min_value < 0: + if positive and min_value is not None and min_value <= 0: raise ValueError( - 'Cannot combine positive=True and negative min_value') + 'Cannot combine positive=True with negative or zero min_value') left_digits = left_digits if left_digits is not None else ( self.random_int(1, sys.float_info.dig)) @@ -87,7 +87,10 @@ def pyfloat(self, left_digits=None, right_digits=None, positive=False, sign = '+' if positive else self.random_element(('+', '-')) left_number = self.random_number(left_digits) - return float(f'{sign}{left_number}.{self.random_number(right_digits)}') + result = float(f'{sign}{left_number}.{self.random_number(right_digits)}') + if positive and result == 0: + result += sys.float_info.epsilon + return result def _safe_random_int(self, min_value, max_value, positive): orig_min_value = min_value diff --git a/tests/providers/test_python.py b/tests/providers/test_python.py index 6a8fa98119..7dee2b8896 100644 --- a/tests/providers/test_python.py +++ b/tests/providers/test_python.py @@ -63,7 +63,7 @@ def test_right_digits(self): def test_positive(self): result = self.fake.pyfloat(positive=True) - self.assertGreaterEqual(result, 0) + self.assertGreater(result, 0) self.assertEqual(result, abs(result)) def test_min_value(self): @@ -99,7 +99,7 @@ def test_max_value_and_positive(self): result = self.fake.pyfloat(positive=True, max_value=100) self.assertLessEqual(result, 100) - self.assertGreaterEqual(result, 0) + self.assertGreater(result, 0) def test_positive_and_min_value_incompatible(self): """ @@ -108,7 +108,7 @@ def test_positive_and_min_value_incompatible(self): """ expected_message = ( - "Cannot combine positive=True and negative min_value" + "Cannot combine positive=True with negative or zero min_value" ) with self.assertRaises(ValueError) as raises: self.fake.pyfloat(min_value=-100, positive=True) @@ -116,6 +116,14 @@ def test_positive_and_min_value_incompatible(self): message = str(raises.exception) self.assertEqual(message, expected_message) + def test_positive_doesnt_return_zero(self): + """ + Choose the right_digits and max_value so it's guaranteed to return zero, + then watch as it doesn't because positive=True + """ + result = self.fake.pyfloat(positive=True, right_digits=0, max_value=1) + self.assertGreater(result, 0) + class TestPystrFormat(unittest.TestCase):