Repository: joke2k/faker
Pull request #1894 (2023-08-04 15:55:47)

Add weigthing to dynamic providers
### What does this change

`DynamicProvider` now accept weighted elements if provided an `OrderedDict`

### What was wrong

`DynamicProvider` were not taking weights into account.

See Issue #1892 

Also fixes a C419 flake8 error on a test file.



Patch:
diff --git a/faker/providers/__init__.py b/faker/providers/__init__.py
index e4932a4d..ff1b0a1b 100644
--- a/faker/providers/__init__.py
+++ b/faker/providers/__init__.py
@@ -723,8 +723,12 @@ class DynamicProvider(BaseProvider):
         """Add new element."""
         self.elements.append(element)
 
-    def get_random_value(self) -> Any:
+    def get_random_value(self, use_weighting: bool = True) -> Any:
+        """Returns a random value for this provider.
+
+        :param use_weighting: boolean option to use weighting. Defaults to True
+        """
         if not self.elements or len(self.elements) == 0:
             raise ValueError("Elements should be a list of values the provider samples from")
 
-        return self.random_element(self.elements)
+        return self.random_elements(self.elements, length=1, use_weighting=use_weighting)[0]


Test patch:
diff --git a/tests/providers/test_dynamic.py b/tests/providers/test_dynamic.py
index 24204f27..fcb7fae5 100644
--- a/tests/providers/test_dynamic.py
+++ b/tests/providers/test_dynamic.py
@@ -1,3 +1,5 @@
+from typing import OrderedDict
+
 import pytest
 
 from faker import Faker
@@ -70,3 +72,51 @@ class TestDynamicProvider:
         provider.add_element("two")
 
         assert faker.my_provider() in ("one", "two")
+
+    def test_weighted_dynamic_with_use_weighting(self):
+        elements = OrderedDict(
+            [
+                ("A", 0.75),
+                ("B", 0.25),
+                ("C", 0.)
+            ]
+        )
+        provider_name = "my_provider"
+        provider = DynamicProvider(
+            provider_name=provider_name,
+            elements=elements,
+        )
+        faker = Faker()
+        faker.add_provider(provider)
+
+        fake_data = [
+            faker.my_provider(use_weighting=True)
+            for _ in range(10_000)
+        ]
+
+        for i in fake_data:
+            assert i in {"A", "B"}
+
+    def test_weighted_dynamic_without_use_weighting(self):
+        elements = OrderedDict(
+            [
+                ("A", 0.75),
+                ("B", 0.25),
+                ("C", 0.)
+            ]
+        )
+        provider_name = "my_provider"
+        provider = DynamicProvider(
+            provider_name=provider_name,
+            elements=elements,
+        )
+        faker = Faker()
+        faker.add_provider(provider)
+
+        fake_data = [
+            faker.my_provider(use_weighting=False)
+            for _ in range(10_000)
+        ]
+
+        for i in fake_data:
+            assert i in {"A", "B", "C"}
diff --git a/tests/providers/test_phone_number.py b/tests/providers/test_phone_number.py
index 1bb38daf..ff3c58ab 100644
--- a/tests/providers/test_phone_number.py
+++ b/tests/providers/test_phone_number.py
@@ -363,7 +363,14 @@ class TestFrFr:
         ]
         for _ in range(num_samples):
             phone_number = faker.phone_number()
-            assert any([re.match(pattern, phone_number) for pattern in patterns])
+
+            pattern_is_found = False
+
+            for pattern in patterns:
+                if re.match(pattern, phone_number):
+                    pattern_is_found = True
+                    break
+            assert pattern_is_found
 
 
 class TestEnUs:
@@ -378,4 +385,10 @@ class TestEnUs:
         patterns = [pattern_no_whitespaces, pattern_dashes, pattern_parens]
         for _ in range(num_samples):
             phone_number = faker.basic_phone_number()
-            assert any([re.match(pattern, phone_number) for pattern in patterns])
+
+            pattern_is_found = False
+            for pattern in patterns:
+                if re.match(pattern, phone_number):
+                    pattern_is_found = True
+                    break
+            assert pattern_is_found