Skip to content

Commit

Permalink
Fix pyfloat returning zeros when positive=True (#1393)
Browse files Browse the repository at this point in the history
* change error handling in pyfloat so you can't request a zero min value with positive=True

* fix pyfloat to return something barely greater than zero when positive=True

* fix style violation
  • Loading branch information
sciencectn authored Feb 3, 2021
1 parent b2f787c commit 47925ed
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 6 deletions.
9 changes: 6 additions & 3 deletions faker/providers/python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand Down
14 changes: 11 additions & 3 deletions tests/providers/test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
"""
Expand All @@ -108,14 +108,22 @@ 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)

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):

Expand Down

0 comments on commit 47925ed

Please sign in to comment.