Repository: joke2k/faker
Pull request #418 (2016-11-02 17:00:17)

Fix `pyfloat`


Patch:
diff --git a/faker/providers/python/__init__.py b/faker/providers/python/__init__.py
index f65257c2..729b742b 100644
--- a/faker/providers/python/__init__.py
+++ b/faker/providers/python/__init__.py
@@ -40,12 +40,21 @@ class Provider(BaseProvider):
 
     @classmethod
     def pyfloat(cls, left_digits=None, right_digits=None, positive=False):
-        left_digits = left_digits or cls.random_int(1, sys.float_info.dig)
-        right_digits = right_digits or cls.random_int(0, sys.float_info.dig - left_digits)
-        sign = 1 if positive or cls.random_int(0, 1) else -1
+        if left_digits is not None and left_digits <= 0:
+            raise ValueError('A float number cannot have less than 1 digit in '
+                             'integer part')
+        if right_digits is not None and right_digits <= 0:
+            raise ValueError('A float number should have fractional part')
+
+        left_digits = left_digits if left_digits is not None else (
+            cls.random_int(1, sys.float_info.dig))
+        right_digits = right_digits if right_digits is not None else (
+            cls.random_int(0, sys.float_info.dig-left_digits))
+        sign = 1 if positive else cls.random_element((-1, 1))
 
         return float("{0}.{1}".format(
-            sign * cls.random_number(left_digits), cls.random_number(right_digits)
+            sign * cls.random_number(left_digits),
+            cls.random_number(right_digits)
         ))
 
     @classmethod


Test patch:
diff --git a/faker/tests/__init__.py b/faker/tests/__init__.py
index 214bf5f1..45198bbf 100644
--- a/faker/tests/__init__.py
+++ b/faker/tests/__init__.py
@@ -523,6 +523,20 @@ class FactoryTestCase(unittest.TestCase):
         characters = provider.pystr(min_chars=10, max_chars=255)
         self.assertTrue((len(characters) >= 10))
 
+    def test_random_pyfloat(self):
+        from faker.providers.python import Provider
+        provider = Provider(None)
+
+        self.assertTrue(0 <= abs(provider.pyfloat(left_digits=1)) < 10)
+        with self.assertRaises(ValueError,
+                               msg='A float number cannot have less than 1 '
+                               'digit in integer part'):
+            provider.pyfloat(left_digits=0)
+        with self.assertRaises(ValueError,
+                               msg='A float number should have fractional '
+                               'part'):
+            provider.pyfloat(right_digits=0)
+
     def test_us_ssn_valid(self):
         from faker.providers.ssn.en_US import Provider
 
@@ -540,7 +554,7 @@ class FactoryTestCase(unittest.TestCase):
         from faker.providers.ssn.nl_BE import Provider
 
         provider = Provider(None)
-        
+
         for i in range (1000):
             ssn = provider.ssn()
             self.assertEqual(len(ssn), 11)
@@ -553,7 +567,7 @@ class FactoryTestCase(unittest.TestCase):
             # Check that the sequence nr is between 1 inclusive and 998 inclusive
             self.assertGreater(gen_seq_as_int,0)
             self.assertLessEqual(gen_seq_as_int, 998)
-            
+
             # validate checksum calculation
             # Since the century is not part of ssn, try both below and above year 2000
             ssn_below = int(ssn[0:9])
@@ -562,7 +576,7 @@ class FactoryTestCase(unittest.TestCase):
             chksum_above = 97 - (ssn_above % 97)
             results = [ chksum_above, chksum_below ]
             self.assertIn(gen_chksum_as_int,results)
-            
+
     def test_email(self):
         from faker import Factory