Repository: joke2k/faker

Issue:
Unicity and localization
* Faker version: 17.4.0
* OS: Archlinux

It seems that uniqueness and localization cannot be used together:

```python
>>> from faker import Faker
... fake = Faker(['it_IT', 'en_US', 'ja_JP'])
>>> fake['it_IT'].name()
'Giuseppina Juvara'
>>> fake['it_IT'].unique.name()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Generator' object has no attribute 'unique'

>>> fake.unique.name()
'石井 翔太'
>>> fake.unique['it_IT'].name()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'UniqueProxy' object is not subscriptable
```

I would lo to be able to use both features at the same time!




Discussion:
This issue is stale because it has been open for 30 days with no activity.
Please stale bot, let this ticket open.
This issue is stale because it has been open for 30 days with no activity.
This issue is still relevant.
This issue is stale because it has been open for 30 days with no activity.
I still don't agree 😮‍💨
Feel free to propose a corresponding PR.



Patch:
diff --git a/faker/proxy.py b/faker/proxy.py
index 653a5943d0..03a6e42e84 100644
--- a/faker/proxy.py
+++ b/faker/proxy.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import copy
 import functools
 import re
@@ -35,7 +37,7 @@ def __init__(
         use_weighting: bool = True,
         **config: Any,
     ) -> None:
-        self._factory_map = OrderedDict()
+        self._factory_map: OrderedDict[str, Generator | Faker] = OrderedDict()
         self._weights = None
         self._unique_proxy = UniqueProxy(self)
         self._optional_proxy = OptionalProxy(self)
@@ -54,7 +56,7 @@ def __init__(
                 if final_locale not in locales:
                     locales.append(final_locale)
 
-        elif isinstance(locale, OrderedDict):
+        elif isinstance(locale, (OrderedDict, dict)):
             assert all(isinstance(v, (int, float)) for v in locale.values())
             odict = OrderedDict()
             for k, v in locale.items():
@@ -66,15 +68,25 @@ def __init__(
         else:
             locales = [DEFAULT_LOCALE]
 
-        for locale in locales:
-            self._factory_map[locale] = Factory.create(
-                locale,
+        if len(locales) == 1:
+            self._factory_map[locales[0]] = Factory.create(
+                locales[0],
                 providers,
                 generator,
                 includes,
                 use_weighting=use_weighting,
                 **config,
             )
+        else:
+            for locale in locales:
+                self._factory_map[locale] = Faker(
+                    locale,
+                    providers,
+                    generator,
+                    includes,
+                    use_weighting=use_weighting,
+                    **config,
+                )
 
         self._locales = locales
         self._factories = list(self._factory_map.values())
@@ -85,8 +97,12 @@ def __dir__(self):
             attributes |= {attr for attr in dir(factory) if not attr.startswith("_")}
         return sorted(attributes)
 
-    def __getitem__(self, locale: str) -> Generator:
-        return self._factory_map[locale.replace("-", "_")]
+    def __getitem__(self, locale: str) -> Faker:
+        if locale.replace("-", "_") in self.locales and len(self.locales) == 1:
+            return self
+        instance = self._factory_map[locale.replace("-", "_")]
+        assert isinstance(instance, Faker)  # for mypy
+        return instance
 
     def __getattribute__(self, attr: str) -> Any:
         """
@@ -273,10 +289,10 @@ def weights(self) -> Optional[List[Union[int, float]]]:
         return self._weights
 
     @property
-    def factories(self) -> List[Generator]:
+    def factories(self) -> List[Generator | Faker]:
         return self._factories
 
-    def items(self) -> List[Tuple[str, Generator]]:
+    def items(self) -> List[Tuple[str, Generator | Faker]]:
         return list(self._factory_map.items())
 
 


Test patch:
diff --git a/tests/providers/test_misc.py b/tests/providers/test_misc.py
index ec9fe57a25..df735eee4f 100644
--- a/tests/providers/test_misc.py
+++ b/tests/providers/test_misc.py
@@ -423,7 +423,7 @@ def test_dsv_with_row_ids(self, faker, num_samples):
     def test_dsv_data_columns(self, faker):
         num_rows = 10
         data_columns = ["{{name}}", "#??-####", "{{address}}", "{{phone_number}}"]
-        with patch.object(faker["en_US"], "pystr_format") as mock_pystr_format:
+        with patch.object(faker["en_US"].factories[0], "pystr_format") as mock_pystr_format:
             mock_pystr_format.assert_not_called()
             faker.dsv(data_columns=data_columns, num_rows=num_rows)
 
diff --git a/tests/providers/test_python.py b/tests/providers/test_python.py
index 6342bfb9eb..4935528eb8 100644
--- a/tests/providers/test_python.py
+++ b/tests/providers/test_python.py
@@ -523,7 +523,7 @@ def setUp(self):
         Faker.seed(0)
 
     def test_formatter_invocation(self):
-        with patch.object(self.fake["en_US"], "foo") as mock_foo:
+        with patch.object(self.fake["en_US"].factories[0], "foo") as mock_foo:
             with patch("faker.providers.BaseProvider.bothify", wraps=self.fake.bothify) as mock_bothify:
                 mock_foo.return_value = "barbar"
                 value = self.fake.pystr_format("{{foo}}?#?{{foo}}?#?{{foo}}", letters="abcde")
diff --git a/tests/test_proxy.py b/tests/test_proxy.py
index 322bc39630..8b4b6d6316 100644
--- a/tests/test_proxy.py
+++ b/tests/test_proxy.py
@@ -103,14 +103,14 @@ def test_items(self):
         fake = Faker(locale)
         for locale_name, factory in fake.items():
             assert locale_name in processed_locale
-            assert isinstance(factory, Generator)
+            assert isinstance(factory, (Generator, Faker))
 
     def test_dunder_getitem(self):
         locale = ["de_DE", "en-US", "en-PH", "ja_JP"]
         fake = Faker(locale)
 
         for code in locale:
-            assert isinstance(fake[code], Generator)
+            assert isinstance(fake[code], (Generator, Faker))
 
         with pytest.raises(KeyError):
             fake["en_GB"]