Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/faker/generator.py: 50%
98 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import random as random_module
2import re
4from typing import TYPE_CHECKING, Any, Callable, Dict, Hashable, List, Optional
6from .typing import SeedType
8if TYPE_CHECKING: 8 ↛ 9line 8 didn't jump to line 9, because the condition on line 8 was never true
9 from .providers import BaseProvider
11_re_token = re.compile(r"\{\{\s*(\w+)(:\s*\w+?)?\s*\}\}")
12random = random_module.Random()
13mod_random = random # compat with name released in 0.8
16Sentinel = object()
19class Generator:
21 __config: Dict[str, Dict[Hashable, Any]] = {
22 "arguments": {},
23 }
25 _is_seeded = False
26 _global_seed = Sentinel
28 def __init__(self, **config: Dict) -> None:
29 self.providers: List["BaseProvider"] = []
30 self.__config = dict(list(self.__config.items()) + list(config.items()))
31 self.__random = random
33 def add_provider(self, provider: "BaseProvider") -> None:
35 if isinstance(provider, type): 35 ↛ 36line 35 didn't jump to line 36, because the condition on line 35 was never true
36 provider = provider(self)
38 self.providers.insert(0, provider)
40 for method_name in dir(provider):
41 # skip 'private' method
42 if method_name.startswith("_"):
43 continue
45 faker_function = getattr(provider, method_name)
47 if callable(faker_function):
48 # add all faker method to generator
49 self.set_formatter(method_name, faker_function)
51 def provider(self, name: str) -> Optional["BaseProvider"]:
52 try:
53 lst = [p for p in self.get_providers() if hasattr(p, "__provider__") and p.__provider__ == name.lower()]
54 return lst[0]
55 except IndexError:
56 return None
58 def get_providers(self) -> List["BaseProvider"]:
59 """Returns added providers."""
60 return self.providers
62 @property
63 def random(self) -> random_module.Random:
64 return self.__random
66 @random.setter
67 def random(self, value: random_module.Random) -> None:
68 self.__random = value
70 def seed_instance(self, seed: Optional[SeedType] = None) -> "Generator":
71 """Calls random.seed"""
72 if self.__random == random:
73 # create per-instance random obj when first time seed_instance() is
74 # called
75 self.__random = random_module.Random()
76 self.__random.seed(seed)
77 self._is_seeded = True
78 return self
80 @classmethod
81 def seed(cls, seed: Optional[SeedType] = None) -> None:
82 random.seed(seed)
83 cls._global_seed = seed
84 cls._is_seeded = True
86 def format(self, formatter: str, *args: Any, **kwargs: Any) -> str:
87 """
88 This is a secure way to make a fake from another Provider.
89 """
90 return self.get_formatter(formatter)(*args, **kwargs)
92 def get_formatter(self, formatter: str) -> Callable:
93 try:
94 return getattr(self, formatter)
95 except AttributeError:
96 if "locale" in self.__config:
97 msg = f'Unknown formatter {formatter!r} with locale {self.__config["locale"]!r}'
98 else:
99 raise AttributeError(f"Unknown formatter {formatter!r}")
100 raise AttributeError(msg)
102 def set_formatter(self, name: str, method: Callable) -> None:
103 """
104 This method adds a provider method to generator.
105 Override this method to add some decoration or logging stuff.
106 """
107 setattr(self, name, method)
109 def set_arguments(self, group: str, argument: str, value: Optional[Any] = None) -> None:
110 """
111 Creates an argument group, with an individual argument or a dictionary
112 of arguments. The argument groups is used to apply arguments to tokens,
113 when using the generator.parse() method. To further manage argument
114 groups, use get_arguments() and del_arguments() methods.
116 generator.set_arguments('small', 'max_value', 10)
117 generator.set_arguments('small', {'min_value': 5, 'max_value': 10})
118 """
119 if group not in self.__config["arguments"]:
120 self.__config["arguments"][group] = {}
122 if isinstance(argument, dict):
123 self.__config["arguments"][group] = argument
124 elif not isinstance(argument, str):
125 raise ValueError("Arguments must be either a string or dictionary")
126 else:
127 self.__config["arguments"][group][argument] = value
129 def get_arguments(self, group: str, argument: Optional[str] = None) -> Any:
130 """
131 Get the value of an argument configured within a argument group, or
132 the entire group as a dictionary. Used in conjunction with the
133 set_arguments() method.
135 generator.get_arguments('small', 'max_value')
136 generator.get_arguments('small')
137 """
138 if group in self.__config["arguments"] and argument:
139 result = self.__config["arguments"][group].get(argument)
140 else:
141 result = self.__config["arguments"].get(group)
143 return result
145 def del_arguments(self, group: str, argument: Optional[str] = None) -> Any:
146 """
147 Delete an argument from an argument group or the entire argument group.
148 Used in conjunction with the set_arguments() method.
150 generator.del_arguments('small')
151 generator.del_arguments('small', 'max_value')
152 """
153 if group in self.__config["arguments"]:
154 if argument:
155 result = self.__config["arguments"][group].pop(argument)
156 else:
157 result = self.__config["arguments"].pop(group)
158 else:
159 result = None
161 return result
163 def parse(self, text: str) -> str:
164 """
165 Replaces tokens like '{{ tokenName }}' or '{{tokenName}}' in a string with
166 the result from the token method call. Arguments can be parsed by using an
167 argument group. For more information on the use of argument groups, please
168 refer to the set_arguments() method.
170 Example:
172 generator.set_arguments('red_rgb', {'hue': 'red', 'color_format': 'rgb'})
173 generator.set_arguments('small', 'max_value', 10)
175 generator.parse('{{ color:red_rgb }} - {{ pyint:small }}')
176 """
177 return _re_token.sub(self.__format_token, text)
179 def __format_token(self, matches):
180 formatter, argument_group = list(matches.groups())
181 argument_group = argument_group.lstrip(":").strip() if argument_group else ""
183 if argument_group: 183 ↛ 184line 183 didn't jump to line 184, because the condition on line 183 was never true
184 try:
185 arguments = self.__config["arguments"][argument_group]
186 except KeyError:
187 raise AttributeError(f"Unknown argument group {argument_group!r}")
189 formatted = str(self.format(formatter, **arguments))
190 else:
191 formatted = str(self.format(formatter))
193 return "".join(formatted)