We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Faker returns one value when using multiple locales
* Faker version: 13.11
* OS: Mac OS Monterey
Computer: MacBook Pro (14-inch, 2021)

Brief summary of the issue goes here.
If using multiple locales, faker only makes one choice. This only happens when you select multiple locales

### Steps to reproduce

```
from faker import Faker

fake = Faker(["en_GB", "fr_FR", "en_IN"])
Faker.seed(0)
for _ in range(5):
    print(fake.date_time_this_year())

```

### Expected behavior
returns
```
2022-03-16 19:22:23
2022-03-23 16:00:20
2022-01-08 20:40:15
2022-02-20 06:38:22
2022-04-10 06:42:46
```

### Actual behavior
returns
```
2022-03-23 16:00:20
2022-03-23 16:00:20
2022-03-23 16:00:20
2022-03-23 16:00:20
2022-03-23 16:00:20

```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `faker/proxy.py`
Content:
```
1 import copy
2 import functools
3 import re
4 
5 from collections import OrderedDict
6 from random import Random
7 from typing import Any, Callable, Dict, List, Optional, Pattern, Sequence, Tuple, Union
8 
9 from .config import DEFAULT_LOCALE
10 from .exceptions import UniquenessException
11 from .factory import Factory
12 from .generator import Generator, Sentinel, random
13 from .typing import SeedType
14 from .utils.distribution import choices_distribution
15 
16 _UNIQUE_ATTEMPTS = 1000
17 
18 
19 class Faker:
20     """Proxy class capable of supporting multiple locales"""
21 
22     cache_pattern: Pattern = re.compile(r"^_cached_\w*_mapping$")
23     generator_attrs = [
24         attr for attr in dir(Generator) if not attr.startswith("__") and attr not in ["seed", "seed_instance", "random"]
25     ]
26 
27     def __init__(
28         self,
29         locale: Optional[Union[str, Sequence[str], Dict[str, Union[int, float]]]] = None,
30         providers: Optional[List[str]] = None,
31         generator: Optional[Generator] = None,
32         includes: Optional[List[str]] = None,
33         use_weighting: bool = True,
34         **config: Any,
35     ) -> None:
36         self._factory_map = OrderedDict()
37         self._weights = None
38         self._unique_proxy = UniqueProxy(self)
39 
40         if isinstance(locale, str):
41             locales = [locale.replace("-", "_")]
42 
43         # This guarantees a FIFO ordering of elements in `locales` based on the final
44         # locale string while discarding duplicates after processing
45         elif isinstance(locale, (list, tuple, set)):
46             locales = []
47             for code in locale:
48                 if not isinstance(code, str):
49                     raise TypeError('The locale "%s" must be a string.' % str(code))
50                 final_locale = code.replace("-", "_")
51                 if final_locale not in locales:
52                     locales.append(final_locale)
53 
54         elif isinstance(locale, OrderedDict):
55             assert all(isinstance(v, (int, float)) for v in locale.values())
56             odict = OrderedDict()
57             for k, v in locale.items():
58                 key = k.replace("-", "_")
59                 odict[key] = v
60             locales = list(odict.keys())
61             self._weights = list(odict.values())
62 
63         else:
64             locales = [DEFAULT_LOCALE]
65 
66         for locale in locales:
67             self._factory_map[locale] = Factory.create(
68                 locale,
69                 providers,
70                 generator,
71                 includes,
72                 use_weighting=use_weighting,
73                 **config,
74             )
75 
76         self._locales = locales
77         self._factories = list(self._factory_map.values())
78 
79     def __dir__(self):
80         attributes = set(super(Faker, self).__dir__())
81         for factory in self.factories:
82             attributes |= {attr for attr in dir(factory) if not attr.startswith("_")}
83         return sorted(attributes)
84 
85     def __getitem__(self, locale: str) -> Generator:
86         return self._factory_map[locale.replace("-", "_")]
87 
88     def __getattribute__(self, attr: str) -> Any:
89         """
90         Handles the "attribute resolution" behavior for declared members of this proxy class
91 
92         The class method `seed` cannot be called from an instance.
93 
94         :param attr: attribute name
95         :return: the appropriate attribute
96         """
97         if attr == "seed":
98             msg = "Calling `.seed()` on instances is deprecated. " "Use the class method `Faker.seed()` instead."
99             raise TypeError(msg)
100         else:
101             return super().__getattribute__(attr)
102 
103     def __getattr__(self, attr: str) -> Any:
104         """
105         Handles cache access and proxying behavior
106 
107         :param attr: attribute name
108         :return: the appropriate attribute
109         """
110         if len(self._factories) == 1:
111             return getattr(self._factories[0], attr)
112         elif attr in self.generator_attrs:
113             msg = "Proxying calls to `%s` is not implemented in multiple locale mode." % attr
114             raise NotImplementedError(msg)
115         elif self.cache_pattern.match(attr):
116             msg = "Cached attribute `%s` does not exist" % attr
117             raise AttributeError(msg)
118         else:
119             factory = self._select_factory(attr)
120             return getattr(factory, attr)
121 
122     def __deepcopy__(self, memodict: Dict = {}) -> "Faker":
123         cls = self.__class__
124         result = cls.__new__(cls)
125         result._locales = copy.deepcopy(self._locales)
126         result._factories = copy.deepcopy(self._factories)
127         result._factory_map = copy.deepcopy(self._factory_map)
128         result._weights = copy.deepcopy(self._weights)
129         result._unique_proxy = UniqueProxy(self)
130         result._unique_proxy._seen = {k: {result._unique_proxy._sentinel} for k in self._unique_proxy._seen.keys()}
131         return result
132 
133     def __setstate__(self, state: Any) -> None:
134         self.__dict__.update(state)
135 
136     @property
137     def unique(self) -> "UniqueProxy":
138         return self._unique_proxy
139 
140     def _select_factory(self, method_name: str) -> Factory:
141         """
142         Returns a random factory that supports the provider method
143 
144         :param method_name: Name of provider method
145         :return: A factory that supports the provider method
146         """
147 
148         factories, weights = self._map_provider_method(method_name)
149 
150         if len(factories) == 0:
151             msg = f"No generator object has attribute {method_name!r}"
152             raise AttributeError(msg)
153         elif len(factories) == 1:
154             return factories[0]
155 
156         if Generator._global_seed is not Sentinel:
157             random.seed(Generator._global_seed)  # type: ignore
158         if weights:
159             factory = self._select_factory_distribution(factories, weights)
160         else:
161             factory = self._select_factory_choice(factories)
162         return factory
163 
164     def _select_factory_distribution(self, factories, weights):
165         return choices_distribution(factories, weights, random, length=1)[0]
166 
167     def _select_factory_choice(self, factories):
168         return random.choice(factories)
169 
170     def _map_provider_method(self, method_name: str) -> Tuple[List[Factory], Optional[List[float]]]:
171         """
172         Creates a 2-tuple of factories and weights for the given provider method name
173 
174         The first element of the tuple contains a list of compatible factories.
175         The second element of the tuple contains a list of distribution weights.
176 
177         :param method_name: Name of provider method
178         :return: 2-tuple (factories, weights)
179         """
180 
181         # Return cached mapping if it exists for given method
182         attr = f"_cached_{method_name}_mapping"
183         if hasattr(self, attr):
184             return getattr(self, attr)
185 
186         # Create mapping if it does not exist
187         if self._weights:
188             value = [
189                 (factory, weight)
190                 for factory, weight in zip(self.factories, self._weights)
191                 if hasattr(factory, method_name)
192             ]
193             factories, weights = zip(*value)
194             mapping = list(factories), list(weights)
195         else:
196             value = [factory for factory in self.factories if hasattr(factory, method_name)]  # type: ignore
197             mapping = value, None  # type: ignore
198 
199         # Then cache and return results
200         setattr(self, attr, mapping)
201         return mapping
202 
203     @classmethod
204     def seed(cls, seed: Optional[SeedType] = None) -> None:
205         """
206         Hashables the shared `random.Random` object across all factories
207 
208         :param seed: seed value
209         """
210         Generator.seed(seed)
211 
212     def seed_instance(self, seed: Optional[SeedType] = None) -> None:
213         """
214         Creates and seeds a new `random.Random` object for each factory
215 
216         :param seed: seed value
217         """
218         for factory in self._factories:
219             factory.seed_instance(seed)
220 
221     def seed_locale(self, locale: str, seed: Optional[SeedType] = None) -> None:
222         """
223         Creates and seeds a new `random.Random` object for the factory of the specified locale
224 
225         :param locale: locale string
226         :param seed: seed value
227         """
228         self._factory_map[locale.replace("-", "_")].seed_instance(seed)
229 
230     @property
231     def random(self) -> Random:
232         """
233         Proxies `random` getter calls
234 
235         In single locale mode, this will be proxied to the `random` getter
236         of the only internal `Generator` object. Subclasses will have to
237         implement desired behavior in multiple locale mode.
238         """
239 
240         if len(self._factories) == 1:
241             return self._factories[0].random
242         else:
243             msg = "Proxying `random` getter calls is not implemented in multiple locale mode."
244             raise NotImplementedError(msg)
245 
246     @random.setter
247     def random(self, value: Random) -> None:
248         """
249         Proxies `random` setter calls
250 
251         In single locale mode, this will be proxied to the `random` setter
252         of the only internal `Generator` object. Subclasses will have to
253         implement desired behavior in multiple locale mode.
254         """
255 
256         if len(self._factories) == 1:
257             self._factories[0].random = value
258         else:
259             msg = "Proxying `random` setter calls is not implemented in multiple locale mode."
260             raise NotImplementedError(msg)
261 
262     @property
263     def locales(self) -> List[str]:
264         return list(self._locales)
265 
266     @property
267     def weights(self) -> Optional[List[Union[int, float]]]:
268         return self._weights
269 
270     @property
271     def factories(self) -> List[Generator]:
272         return self._factories
273 
274     def items(self) -> List[Tuple[str, Generator]]:
275         return list(self._factory_map.items())
276 
277 
278 class UniqueProxy:
279     def __init__(self, proxy: Faker):
280         self._proxy = proxy
281         self._seen: Dict = {}
282         self._sentinel = object()
283 
284     def clear(self) -> None:
285         self._seen = {}
286 
287     def __getattr__(self, name: str) -> Any:
288         obj = getattr(self._proxy, name)
289         if callable(obj):
290             return self._wrap(name, obj)
291         else:
292             raise TypeError("Accessing non-functions through .unique is not supported.")
293 
294     def __getstate__(self):
295         # Copy the object's state from self.__dict__ which contains
296         # all our instance attributes. Always use the dict.copy()
297         # method to avoid modifying the original state.
298         state = self.__dict__.copy()
299         return state
300 
301     def __setstate__(self, state):
302         self.__dict__.update(state)
303 
304     def _wrap(self, name: str, function: Callable) -> Callable:
305         @functools.wraps(function)
306         def wrapper(*args, **kwargs):
307             key = (name, args, tuple(sorted(kwargs.items())))
308 
309             generated = self._seen.setdefault(key, {self._sentinel})
310 
311             # With use of a sentinel value rather than None, we leave
312             # None open as a valid return value.
313             retval = self._sentinel
314 
315             for i in range(_UNIQUE_ATTEMPTS):
316                 if retval not in generated:
317                     break
318                 retval = function(*args, **kwargs)
319             else:
320                 raise UniquenessException(f"Got duplicated values after {_UNIQUE_ATTEMPTS:,} iterations.")
321 
322             generated.add(retval)
323 
324             return retval
325 
326         return wrapper
327
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/faker/proxy.py b/faker/proxy.py
--- a/faker/proxy.py
+++ b/faker/proxy.py
@@ -9,7 +9,7 @@
 from .config import DEFAULT_LOCALE
 from .exceptions import UniquenessException
 from .factory import Factory
-from .generator import Generator, Sentinel, random
+from .generator import Generator, random
 from .typing import SeedType
 from .utils.distribution import choices_distribution
 
@@ -153,8 +153,6 @@
         elif len(factories) == 1:
             return factories[0]
 
-        if Generator._global_seed is not Sentinel:
-            random.seed(Generator._global_seed)  # type: ignore
         if weights:
             factory = self._select_factory_distribution(factories, weights)
         else:

{"golden_diff": "diff --git a/faker/proxy.py b/faker/proxy.py\n--- a/faker/proxy.py\n+++ b/faker/proxy.py\n@@ -9,7 +9,7 @@\n from .config import DEFAULT_LOCALE\n from .exceptions import UniquenessException\n from .factory import Factory\n-from .generator import Generator, Sentinel, random\n+from .generator import Generator, random\n from .typing import SeedType\n from .utils.distribution import choices_distribution\n \n@@ -153,8 +153,6 @@\n         elif len(factories) == 1:\n             return factories[0]\n \n-        if Generator._global_seed is not Sentinel:\n-            random.seed(Generator._global_seed)  # type: ignore\n         if weights:\n             factory = self._select_factory_distribution(factories, weights)\n         else:\n", "issue": "Faker returns one value when using multiple locales\n* Faker version: 13.11\r\n* OS: Mac OS Monterey\r\nComputer: MacBook Pro (14-inch, 2021)\r\n\r\nBrief summary of the issue goes here.\r\nIf using multiple locales, faker only makes one choice. This only happens when you select multiple locales\r\n\r\n### Steps to reproduce\r\n\r\n```\r\nfrom faker import Faker\r\n\r\nfake = Faker([\"en_GB\", \"fr_FR\", \"en_IN\"])\r\nFaker.seed(0)\r\nfor _ in range(5):\r\n    print(fake.date_time_this_year())\r\n\r\n```\r\n\r\n### Expected behavior\r\nreturns\r\n```\r\n2022-03-16 19:22:23\r\n2022-03-23 16:00:20\r\n2022-01-08 20:40:15\r\n2022-02-20 06:38:22\r\n2022-04-10 06:42:46\r\n```\r\n\r\n### Actual behavior\r\nreturns\r\n```\r\n2022-03-23 16:00:20\r\n2022-03-23 16:00:20\r\n2022-03-23 16:00:20\r\n2022-03-23 16:00:20\r\n2022-03-23 16:00:20\r\n\r\n```\n", "before_files": [{"content": "import copy\nimport functools\nimport re\n\nfrom collections import OrderedDict\nfrom random import Random\nfrom typing import Any, Callable, Dict, List, Optional, Pattern, Sequence, Tuple, Union\n\nfrom .config import DEFAULT_LOCALE\nfrom .exceptions import UniquenessException\nfrom .factory import Factory\nfrom .generator import Generator, Sentinel, random\nfrom .typing import SeedType\nfrom .utils.distribution import choices_distribution\n\n_UNIQUE_ATTEMPTS = 1000\n\n\nclass Faker:\n    \"\"\"Proxy class capable of supporting multiple locales\"\"\"\n\n    cache_pattern: Pattern = re.compile(r\"^_cached_\\w*_mapping$\")\n    generator_attrs = [\n        attr for attr in dir(Generator) if not attr.startswith(\"__\") and attr not in [\"seed\", \"seed_instance\", \"random\"]\n    ]\n\n    def __init__(\n        self,\n        locale: Optional[Union[str, Sequence[str], Dict[str, Union[int, float]]]] = None,\n        providers: Optional[List[str]] = None,\n        generator: Optional[Generator] = None,\n        includes: Optional[List[str]] = None,\n        use_weighting: bool = True,\n        **config: Any,\n    ) -> None:\n        self._factory_map = OrderedDict()\n        self._weights = None\n        self._unique_proxy = UniqueProxy(self)\n\n        if isinstance(locale, str):\n            locales = [locale.replace(\"-\", \"_\")]\n\n        # This guarantees a FIFO ordering of elements in `locales` based on the final\n        # locale string while discarding duplicates after processing\n        elif isinstance(locale, (list, tuple, set)):\n            locales = []\n            for code in locale:\n                if not isinstance(code, str):\n                    raise TypeError('The locale \"%s\" must be a string.' % str(code))\n                final_locale = code.replace(\"-\", \"_\")\n                if final_locale not in locales:\n                    locales.append(final_locale)\n\n        elif isinstance(locale, OrderedDict):\n            assert all(isinstance(v, (int, float)) for v in locale.values())\n            odict = OrderedDict()\n            for k, v in locale.items():\n                key = k.replace(\"-\", \"_\")\n                odict[key] = v\n            locales = list(odict.keys())\n            self._weights = list(odict.values())\n\n        else:\n            locales = [DEFAULT_LOCALE]\n\n        for locale in locales:\n            self._factory_map[locale] = Factory.create(\n                locale,\n                providers,\n                generator,\n                includes,\n                use_weighting=use_weighting,\n                **config,\n            )\n\n        self._locales = locales\n        self._factories = list(self._factory_map.values())\n\n    def __dir__(self):\n        attributes = set(super(Faker, self).__dir__())\n        for factory in self.factories:\n            attributes |= {attr for attr in dir(factory) if not attr.startswith(\"_\")}\n        return sorted(attributes)\n\n    def __getitem__(self, locale: str) -> Generator:\n        return self._factory_map[locale.replace(\"-\", \"_\")]\n\n    def __getattribute__(self, attr: str) -> Any:\n        \"\"\"\n        Handles the \"attribute resolution\" behavior for declared members of this proxy class\n\n        The class method `seed` cannot be called from an instance.\n\n        :param attr: attribute name\n        :return: the appropriate attribute\n        \"\"\"\n        if attr == \"seed\":\n            msg = \"Calling `.seed()` on instances is deprecated. \" \"Use the class method `Faker.seed()` instead.\"\n            raise TypeError(msg)\n        else:\n            return super().__getattribute__(attr)\n\n    def __getattr__(self, attr: str) -> Any:\n        \"\"\"\n        Handles cache access and proxying behavior\n\n        :param attr: attribute name\n        :return: the appropriate attribute\n        \"\"\"\n        if len(self._factories) == 1:\n            return getattr(self._factories[0], attr)\n        elif attr in self.generator_attrs:\n            msg = \"Proxying calls to `%s` is not implemented in multiple locale mode.\" % attr\n            raise NotImplementedError(msg)\n        elif self.cache_pattern.match(attr):\n            msg = \"Cached attribute `%s` does not exist\" % attr\n            raise AttributeError(msg)\n        else:\n            factory = self._select_factory(attr)\n            return getattr(factory, attr)\n\n    def __deepcopy__(self, memodict: Dict = {}) -> \"Faker\":\n        cls = self.__class__\n        result = cls.__new__(cls)\n        result._locales = copy.deepcopy(self._locales)\n        result._factories = copy.deepcopy(self._factories)\n        result._factory_map = copy.deepcopy(self._factory_map)\n        result._weights = copy.deepcopy(self._weights)\n        result._unique_proxy = UniqueProxy(self)\n        result._unique_proxy._seen = {k: {result._unique_proxy._sentinel} for k in self._unique_proxy._seen.keys()}\n        return result\n\n    def __setstate__(self, state: Any) -> None:\n        self.__dict__.update(state)\n\n    @property\n    def unique(self) -> \"UniqueProxy\":\n        return self._unique_proxy\n\n    def _select_factory(self, method_name: str) -> Factory:\n        \"\"\"\n        Returns a random factory that supports the provider method\n\n        :param method_name: Name of provider method\n        :return: A factory that supports the provider method\n        \"\"\"\n\n        factories, weights = self._map_provider_method(method_name)\n\n        if len(factories) == 0:\n            msg = f\"No generator object has attribute {method_name!r}\"\n            raise AttributeError(msg)\n        elif len(factories) == 1:\n            return factories[0]\n\n        if Generator._global_seed is not Sentinel:\n            random.seed(Generator._global_seed)  # type: ignore\n        if weights:\n            factory = self._select_factory_distribution(factories, weights)\n        else:\n            factory = self._select_factory_choice(factories)\n        return factory\n\n    def _select_factory_distribution(self, factories, weights):\n        return choices_distribution(factories, weights, random, length=1)[0]\n\n    def _select_factory_choice(self, factories):\n        return random.choice(factories)\n\n    def _map_provider_method(self, method_name: str) -> Tuple[List[Factory], Optional[List[float]]]:\n        \"\"\"\n        Creates a 2-tuple of factories and weights for the given provider method name\n\n        The first element of the tuple contains a list of compatible factories.\n        The second element of the tuple contains a list of distribution weights.\n\n        :param method_name: Name of provider method\n        :return: 2-tuple (factories, weights)\n        \"\"\"\n\n        # Return cached mapping if it exists for given method\n        attr = f\"_cached_{method_name}_mapping\"\n        if hasattr(self, attr):\n            return getattr(self, attr)\n\n        # Create mapping if it does not exist\n        if self._weights:\n            value = [\n                (factory, weight)\n                for factory, weight in zip(self.factories, self._weights)\n                if hasattr(factory, method_name)\n            ]\n            factories, weights = zip(*value)\n            mapping = list(factories), list(weights)\n        else:\n            value = [factory for factory in self.factories if hasattr(factory, method_name)]  # type: ignore\n            mapping = value, None  # type: ignore\n\n        # Then cache and return results\n        setattr(self, attr, mapping)\n        return mapping\n\n    @classmethod\n    def seed(cls, seed: Optional[SeedType] = None) -> None:\n        \"\"\"\n        Hashables the shared `random.Random` object across all factories\n\n        :param seed: seed value\n        \"\"\"\n        Generator.seed(seed)\n\n    def seed_instance(self, seed: Optional[SeedType] = None) -> None:\n        \"\"\"\n        Creates and seeds a new `random.Random` object for each factory\n\n        :param seed: seed value\n        \"\"\"\n        for factory in self._factories:\n            factory.seed_instance(seed)\n\n    def seed_locale(self, locale: str, seed: Optional[SeedType] = None) -> None:\n        \"\"\"\n        Creates and seeds a new `random.Random` object for the factory of the specified locale\n\n        :param locale: locale string\n        :param seed: seed value\n        \"\"\"\n        self._factory_map[locale.replace(\"-\", \"_\")].seed_instance(seed)\n\n    @property\n    def random(self) -> Random:\n        \"\"\"\n        Proxies `random` getter calls\n\n        In single locale mode, this will be proxied to the `random` getter\n        of the only internal `Generator` object. Subclasses will have to\n        implement desired behavior in multiple locale mode.\n        \"\"\"\n\n        if len(self._factories) == 1:\n            return self._factories[0].random\n        else:\n            msg = \"Proxying `random` getter calls is not implemented in multiple locale mode.\"\n            raise NotImplementedError(msg)\n\n    @random.setter\n    def random(self, value: Random) -> None:\n        \"\"\"\n        Proxies `random` setter calls\n\n        In single locale mode, this will be proxied to the `random` setter\n        of the only internal `Generator` object. Subclasses will have to\n        implement desired behavior in multiple locale mode.\n        \"\"\"\n\n        if len(self._factories) == 1:\n            self._factories[0].random = value\n        else:\n            msg = \"Proxying `random` setter calls is not implemented in multiple locale mode.\"\n            raise NotImplementedError(msg)\n\n    @property\n    def locales(self) -> List[str]:\n        return list(self._locales)\n\n    @property\n    def weights(self) -> Optional[List[Union[int, float]]]:\n        return self._weights\n\n    @property\n    def factories(self) -> List[Generator]:\n        return self._factories\n\n    def items(self) -> List[Tuple[str, Generator]]:\n        return list(self._factory_map.items())\n\n\nclass UniqueProxy:\n    def __init__(self, proxy: Faker):\n        self._proxy = proxy\n        self._seen: Dict = {}\n        self._sentinel = object()\n\n    def clear(self) -> None:\n        self._seen = {}\n\n    def __getattr__(self, name: str) -> Any:\n        obj = getattr(self._proxy, name)\n        if callable(obj):\n            return self._wrap(name, obj)\n        else:\n            raise TypeError(\"Accessing non-functions through .unique is not supported.\")\n\n    def __getstate__(self):\n        # Copy the object's state from self.__dict__ which contains\n        # all our instance attributes. Always use the dict.copy()\n        # method to avoid modifying the original state.\n        state = self.__dict__.copy()\n        return state\n\n    def __setstate__(self, state):\n        self.__dict__.update(state)\n\n    def _wrap(self, name: str, function: Callable) -> Callable:\n        @functools.wraps(function)\n        def wrapper(*args, **kwargs):\n            key = (name, args, tuple(sorted(kwargs.items())))\n\n            generated = self._seen.setdefault(key, {self._sentinel})\n\n            # With use of a sentinel value rather than None, we leave\n            # None open as a valid return value.\n            retval = self._sentinel\n\n            for i in range(_UNIQUE_ATTEMPTS):\n                if retval not in generated:\n                    break\n                retval = function(*args, **kwargs)\n            else:\n                raise UniquenessException(f\"Got duplicated values after {_UNIQUE_ATTEMPTS:,} iterations.\")\n\n            generated.add(retval)\n\n            return retval\n\n        return wrapper\n", "path": "faker/proxy.py"}], "after_files": [{"content": "import copy\nimport functools\nimport re\n\nfrom collections import OrderedDict\nfrom random import Random\nfrom typing import Any, Callable, Dict, List, Optional, Pattern, Sequence, Tuple, Union\n\nfrom .config import DEFAULT_LOCALE\nfrom .exceptions import UniquenessException\nfrom .factory import Factory\nfrom .generator import Generator, random\nfrom .typing import SeedType\nfrom .utils.distribution import choices_distribution\n\n_UNIQUE_ATTEMPTS = 1000\n\n\nclass Faker:\n    \"\"\"Proxy class capable of supporting multiple locales\"\"\"\n\n    cache_pattern: Pattern = re.compile(r\"^_cached_\\w*_mapping$\")\n    generator_attrs = [\n        attr for attr in dir(Generator) if not attr.startswith(\"__\") and attr not in [\"seed\", \"seed_instance\", \"random\"]\n    ]\n\n    def __init__(\n        self,\n        locale: Optional[Union[str, Sequence[str], Dict[str, Union[int, float]]]] = None,\n        providers: Optional[List[str]] = None,\n        generator: Optional[Generator] = None,\n        includes: Optional[List[str]] = None,\n        use_weighting: bool = True,\n        **config: Any,\n    ) -> None:\n        self._factory_map = OrderedDict()\n        self._weights = None\n        self._unique_proxy = UniqueProxy(self)\n\n        if isinstance(locale, str):\n            locales = [locale.replace(\"-\", \"_\")]\n\n        # This guarantees a FIFO ordering of elements in `locales` based on the final\n        # locale string while discarding duplicates after processing\n        elif isinstance(locale, (list, tuple, set)):\n            locales = []\n            for code in locale:\n                if not isinstance(code, str):\n                    raise TypeError('The locale \"%s\" must be a string.' % str(code))\n                final_locale = code.replace(\"-\", \"_\")\n                if final_locale not in locales:\n                    locales.append(final_locale)\n\n        elif isinstance(locale, OrderedDict):\n            assert all(isinstance(v, (int, float)) for v in locale.values())\n            odict = OrderedDict()\n            for k, v in locale.items():\n                key = k.replace(\"-\", \"_\")\n                odict[key] = v\n            locales = list(odict.keys())\n            self._weights = list(odict.values())\n\n        else:\n            locales = [DEFAULT_LOCALE]\n\n        for locale in locales:\n            self._factory_map[locale] = Factory.create(\n                locale,\n                providers,\n                generator,\n                includes,\n                use_weighting=use_weighting,\n                **config,\n            )\n\n        self._locales = locales\n        self._factories = list(self._factory_map.values())\n\n    def __dir__(self):\n        attributes = set(super(Faker, self).__dir__())\n        for factory in self.factories:\n            attributes |= {attr for attr in dir(factory) if not attr.startswith(\"_\")}\n        return sorted(attributes)\n\n    def __getitem__(self, locale: str) -> Generator:\n        return self._factory_map[locale.replace(\"-\", \"_\")]\n\n    def __getattribute__(self, attr: str) -> Any:\n        \"\"\"\n        Handles the \"attribute resolution\" behavior for declared members of this proxy class\n\n        The class method `seed` cannot be called from an instance.\n\n        :param attr: attribute name\n        :return: the appropriate attribute\n        \"\"\"\n        if attr == \"seed\":\n            msg = \"Calling `.seed()` on instances is deprecated. \" \"Use the class method `Faker.seed()` instead.\"\n            raise TypeError(msg)\n        else:\n            return super().__getattribute__(attr)\n\n    def __getattr__(self, attr: str) -> Any:\n        \"\"\"\n        Handles cache access and proxying behavior\n\n        :param attr: attribute name\n        :return: the appropriate attribute\n        \"\"\"\n        if len(self._factories) == 1:\n            return getattr(self._factories[0], attr)\n        elif attr in self.generator_attrs:\n            msg = \"Proxying calls to `%s` is not implemented in multiple locale mode.\" % attr\n            raise NotImplementedError(msg)\n        elif self.cache_pattern.match(attr):\n            msg = \"Cached attribute `%s` does not exist\" % attr\n            raise AttributeError(msg)\n        else:\n            factory = self._select_factory(attr)\n            return getattr(factory, attr)\n\n    def __deepcopy__(self, memodict: Dict = {}) -> \"Faker\":\n        cls = self.__class__\n        result = cls.__new__(cls)\n        result._locales = copy.deepcopy(self._locales)\n        result._factories = copy.deepcopy(self._factories)\n        result._factory_map = copy.deepcopy(self._factory_map)\n        result._weights = copy.deepcopy(self._weights)\n        result._unique_proxy = UniqueProxy(self)\n        result._unique_proxy._seen = {k: {result._unique_proxy._sentinel} for k in self._unique_proxy._seen.keys()}\n        return result\n\n    def __setstate__(self, state: Any) -> None:\n        self.__dict__.update(state)\n\n    @property\n    def unique(self) -> \"UniqueProxy\":\n        return self._unique_proxy\n\n    def _select_factory(self, method_name: str) -> Factory:\n        \"\"\"\n        Returns a random factory that supports the provider method\n\n        :param method_name: Name of provider method\n        :return: A factory that supports the provider method\n        \"\"\"\n\n        factories, weights = self._map_provider_method(method_name)\n\n        if len(factories) == 0:\n            msg = f\"No generator object has attribute {method_name!r}\"\n            raise AttributeError(msg)\n        elif len(factories) == 1:\n            return factories[0]\n\n        if weights:\n            factory = self._select_factory_distribution(factories, weights)\n        else:\n            factory = self._select_factory_choice(factories)\n        return factory\n\n    def _select_factory_distribution(self, factories, weights):\n        return choices_distribution(factories, weights, random, length=1)[0]\n\n    def _select_factory_choice(self, factories):\n        return random.choice(factories)\n\n    def _map_provider_method(self, method_name: str) -> Tuple[List[Factory], Optional[List[float]]]:\n        \"\"\"\n        Creates a 2-tuple of factories and weights for the given provider method name\n\n        The first element of the tuple contains a list of compatible factories.\n        The second element of the tuple contains a list of distribution weights.\n\n        :param method_name: Name of provider method\n        :return: 2-tuple (factories, weights)\n        \"\"\"\n\n        # Return cached mapping if it exists for given method\n        attr = f\"_cached_{method_name}_mapping\"\n        if hasattr(self, attr):\n            return getattr(self, attr)\n\n        # Create mapping if it does not exist\n        if self._weights:\n            value = [\n                (factory, weight)\n                for factory, weight in zip(self.factories, self._weights)\n                if hasattr(factory, method_name)\n            ]\n            factories, weights = zip(*value)\n            mapping = list(factories), list(weights)\n        else:\n            value = [factory for factory in self.factories if hasattr(factory, method_name)]  # type: ignore\n            mapping = value, None  # type: ignore\n\n        # Then cache and return results\n        setattr(self, attr, mapping)\n        return mapping\n\n    @classmethod\n    def seed(cls, seed: Optional[SeedType] = None) -> None:\n        \"\"\"\n        Hashables the shared `random.Random` object across all factories\n\n        :param seed: seed value\n        \"\"\"\n        Generator.seed(seed)\n\n    def seed_instance(self, seed: Optional[SeedType] = None) -> None:\n        \"\"\"\n        Creates and seeds a new `random.Random` object for each factory\n\n        :param seed: seed value\n        \"\"\"\n        for factory in self._factories:\n            factory.seed_instance(seed)\n\n    def seed_locale(self, locale: str, seed: Optional[SeedType] = None) -> None:\n        \"\"\"\n        Creates and seeds a new `random.Random` object for the factory of the specified locale\n\n        :param locale: locale string\n        :param seed: seed value\n        \"\"\"\n        self._factory_map[locale.replace(\"-\", \"_\")].seed_instance(seed)\n\n    @property\n    def random(self) -> Random:\n        \"\"\"\n        Proxies `random` getter calls\n\n        In single locale mode, this will be proxied to the `random` getter\n        of the only internal `Generator` object. Subclasses will have to\n        implement desired behavior in multiple locale mode.\n        \"\"\"\n\n        if len(self._factories) == 1:\n            return self._factories[0].random\n        else:\n            msg = \"Proxying `random` getter calls is not implemented in multiple locale mode.\"\n            raise NotImplementedError(msg)\n\n    @random.setter\n    def random(self, value: Random) -> None:\n        \"\"\"\n        Proxies `random` setter calls\n\n        In single locale mode, this will be proxied to the `random` setter\n        of the only internal `Generator` object. Subclasses will have to\n        implement desired behavior in multiple locale mode.\n        \"\"\"\n\n        if len(self._factories) == 1:\n            self._factories[0].random = value\n        else:\n            msg = \"Proxying `random` setter calls is not implemented in multiple locale mode.\"\n            raise NotImplementedError(msg)\n\n    @property\n    def locales(self) -> List[str]:\n        return list(self._locales)\n\n    @property\n    def weights(self) -> Optional[List[Union[int, float]]]:\n        return self._weights\n\n    @property\n    def factories(self) -> List[Generator]:\n        return self._factories\n\n    def items(self) -> List[Tuple[str, Generator]]:\n        return list(self._factory_map.items())\n\n\nclass UniqueProxy:\n    def __init__(self, proxy: Faker):\n        self._proxy = proxy\n        self._seen: Dict = {}\n        self._sentinel = object()\n\n    def clear(self) -> None:\n        self._seen = {}\n\n    def __getattr__(self, name: str) -> Any:\n        obj = getattr(self._proxy, name)\n        if callable(obj):\n            return self._wrap(name, obj)\n        else:\n            raise TypeError(\"Accessing non-functions through .unique is not supported.\")\n\n    def __getstate__(self):\n        # Copy the object's state from self.__dict__ which contains\n        # all our instance attributes. Always use the dict.copy()\n        # method to avoid modifying the original state.\n        state = self.__dict__.copy()\n        return state\n\n    def __setstate__(self, state):\n        self.__dict__.update(state)\n\n    def _wrap(self, name: str, function: Callable) -> Callable:\n        @functools.wraps(function)\n        def wrapper(*args, **kwargs):\n            key = (name, args, tuple(sorted(kwargs.items())))\n\n            generated = self._seen.setdefault(key, {self._sentinel})\n\n            # With use of a sentinel value rather than None, we leave\n            # None open as a valid return value.\n            retval = self._sentinel\n\n            for i in range(_UNIQUE_ATTEMPTS):\n                if retval not in generated:\n                    break\n                retval = function(*args, **kwargs)\n            else:\n                raise UniquenessException(f\"Got duplicated values after {_UNIQUE_ATTEMPTS:,} iterations.\")\n\n            generated.add(retval)\n\n            return retval\n\n        return wrapper\n", "path": "faker/proxy.py"}]}