Repository: joke2k/faker

Issue:
Decimals returning min value too often, and wrong data type.
* Faker version: 8.14.1

Since latest release this statement produces min value way too often, and it uses min val directly.

8.14.1:
```
>>> f = faker.Faker()
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('2.85')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('7.47')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
0
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('9.69')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
0
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('2.41')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('4.04')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('4.49')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
0
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('3.44')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
0
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('8.88')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
0
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
0
```

8.14.0
```
>>> f = faker.Faker()
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('3.58')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('8.4')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('7.61')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('5.18')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('9.49')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('1.14')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('1.27')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('7.92')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('1.71')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('3.9')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('1.28')
>>> f.pydecimal(left_digits=1, right_digits=2, min_value=0, max_value=10)
Decimal('8.61')
```

It hits the min too often, and when it does it returns the passed in value. Instead if you're going to do that, wrap it in a decimal so it works as before. Most people are probably too lazy to use whole decimal class just to pass in a single number for min/max.


Discussion:
The return type has been fixed in https://github.com/joke2k/faker/pull/1529.

This is still happening in v9.0.0:
```
>>> from faker import Faker
>>> f = Faker()
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('512.05')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('592.87')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('631.51')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('738.22')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('186.98')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('170.53')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('599.69')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('224.40')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('354.14')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('150.84')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('594.07')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('1')
>>> f.pydecimal(left_digits=3, right_digits=2, min_value=1, max_value=999)
Decimal('342.09')
```

Resolving patch:
diff --git a/faker/providers/python/__init__.py b/faker/providers/python/__init__.py
--- a/faker/providers/python/__init__.py
+++ b/faker/providers/python/__init__.py
@@ -185,13 +185,18 @@ def pydecimal(self, left_digits=None, right_digits=None, positive=False,
         if left_digits is None and right_digits is not None:
             left_digits = self.random_int(minimum_left_digits, max_random_digits)
 
-        sign = ''
         left_number = ''.join([str(self.random_digit()) for i in range(0, left_digits)]) or '0'
         if right_digits is not None:
             right_number = ''.join([str(self.random_digit()) for i in range(0, right_digits)])
         else:
             right_number = ''
-        sign = '+' if positive else self.random_element(('+', '-'))
+
+        if min_value is not None and min_value >= 0:
+            sign = '+'
+        elif max_value is not None and max_value <= 0:
+            sign = '-'
+        else:
+            sign = '+' if positive else self.random_element(('+', '-'))
 
         result = Decimal(f'{sign}{left_number}.{right_number}')
 


Test patch:
diff --git a/tests/providers/test_python.py b/tests/providers/test_python.py
--- a/tests/providers/test_python.py
+++ b/tests/providers/test_python.py
@@ -352,6 +352,26 @@ def test_positive_doesnt_return_zero(self):
         result = self.fake.pydecimal(positive=True, right_digits=0, max_value=1)
         self.assertGreater(result, 0)
 
+    def test_min_value_zero_doesnt_return_negative(self):
+        Faker.seed('1')
+        result = self.fake.pydecimal(left_digits=3, right_digits=2, min_value=0, max_value=999)
+        self.assertGreater(result, 0)
+
+    def test_min_value_one_hundred_doesnt_return_negative(self):
+        Faker.seed('1')
+        result = self.fake.pydecimal(left_digits=3, right_digits=2, min_value=100, max_value=999)
+        self.assertGreater(result, 100)
+
+    def test_min_value_minus_one_doesnt_return_positive(self):
+        Faker.seed('5')
+        result = self.fake.pydecimal(left_digits=3, right_digits=2, min_value=-999, max_value=0)
+        self.assertLess(result, 0)
+
+    def test_min_value_minus_one_hundred_doesnt_return_positive(self):
+        Faker.seed('5')
+        result = self.fake.pydecimal(left_digits=3, right_digits=2, min_value=-999, max_value=-100)
+        self.assertLess(result, -100)
+
 
 class TestPystrFormat(unittest.TestCase):