Repository: joke2k/faker
Pull request #1797 (2023-02-17 19:35:30)

Add argument validation to `pybool()`
### What was wrong
`pybool()` didn't have argument validation.

### How this fixes it
I've added argument validation to `pybool()`.

### What does this change
After the patch, an exception would be thrown when invalid `truth_probability` value is provided. 

I'm really not sure about this one, and you may consider this a redundant check.

But it seems to me that when someone provides a probability value of `-5` this may be a clear sign that something's wrong with the client code, thus it's better to report the problem instead of silently ignoring it.

Note that technically this patch may be considered as a breaking change.



Patch:
diff --git a/faker/providers/misc/__init__.py b/faker/providers/misc/__init__.py
index 5fd22ea0..19b07820 100644
--- a/faker/providers/misc/__init__.py
+++ b/faker/providers/misc/__init__.py
@@ -678,7 +678,7 @@ class Provider(BaseProvider):
 
     def _value_format_selection(self, definition: str, **kwargs: Any) -> Union[int, str]:
         """
-        Formats the string in different ways depending on it's contents.
+        Formats the string in different ways depending on its contents.
 
         The return can be the '@word' itself, a '{{ token }}' passed to PyStr,
         or a 'provider:argument_group' format field that returns potentially
@@ -696,12 +696,12 @@ class Provider(BaseProvider):
         if re.match(r"^@.*", definition):
             return definition.lstrip("@")
 
-        # Check if a argument group has been supplied
+        # Check if an argument group has been supplied
         if re.match(r"^[a-zA-Z0-9_-]*:\w", definition):
             definition, argument_group = definition.split(":")
             arguments = self.generator.get_arguments(argument_group.strip())
 
             return self.generator.format(definition.strip(), **arguments)
 
-        # Assume the string is refering to a provider
+        # Assume the string is referring to a provider
         return self.generator.format(definition, **kwargs)
diff --git a/faker/providers/python/__init__.py b/faker/providers/python/__init__.py
index 44758ede..8391c604 100644
--- a/faker/providers/python/__init__.py
+++ b/faker/providers/python/__init__.py
@@ -59,9 +59,13 @@ class Provider(BaseProvider):
         """
         Generates a random boolean, optionally biased towards `True` or `False`.
 
-        :truth_probability: Probability of generating a `True` value.
+        :truth_probability: Probability of generating a `True` value. Must be between `0` and `100` inclusive'.
         :return: Random boolean.
+        :raises ValueError: If invalid `truth_probability` is provided.
         """
+        if truth_probability < 0 or truth_probability > 100:
+            raise ValueError("Invalid `truth_probability` value: must be between `0` and `100` inclusive")
+
         return self.random_int(1, 100) <= truth_probability
 
     def pystr(


Test patch:
diff --git a/tests/providers/test_python.py b/tests/providers/test_python.py
index 21a5f98e..99f4866d 100644
--- a/tests/providers/test_python.py
+++ b/tests/providers/test_python.py
@@ -508,6 +508,20 @@ class TestPython(unittest.TestCase):
     def test_pybool_truth_probability_hundred(self):
         self.__test_pybool_truth_probability(100, deviation_threshold=0)
 
+    def __test_pybool_invalid_truth_probability(self, truth_probability: int):
+        with pytest.raises(ValueError) as exception:
+            self.factory.pybool(truth_probability=truth_probability)
+
+        message_expected = "Invalid `truth_probability` value: must be between `0` and `100` inclusive"
+        message_actual = str(exception.value)
+        assert message_expected == message_actual
+
+    def test_pybool_truth_probability_less_than_zero(self):
+        self.__test_pybool_invalid_truth_probability(-1)
+
+    def test_pybool_truth_probability_more_than_hundred(self):
+        self.__test_pybool_invalid_truth_probability(101)
+
     def test_pytuple(self):
         with warnings.catch_warnings(record=True) as w:
             some_tuple = Faker().pytuple()