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

1import random as random_module 

2import re 

3 

4from typing import TYPE_CHECKING, Any, Callable, Dict, Hashable, List, Optional 

5 

6from .typing import SeedType 

7 

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 

10 

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 

14 

15 

16Sentinel = object() 

17 

18 

19class Generator: 

20 

21 __config: Dict[str, Dict[Hashable, Any]] = { 

22 "arguments": {}, 

23 } 

24 

25 _is_seeded = False 

26 _global_seed = Sentinel 

27 

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 

32 

33 def add_provider(self, provider: "BaseProvider") -> None: 

34 

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) 

37 

38 self.providers.insert(0, provider) 

39 

40 for method_name in dir(provider): 

41 # skip 'private' method 

42 if method_name.startswith("_"): 

43 continue 

44 

45 faker_function = getattr(provider, method_name) 

46 

47 if callable(faker_function): 

48 # add all faker method to generator 

49 self.set_formatter(method_name, faker_function) 

50 

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 

57 

58 def get_providers(self) -> List["BaseProvider"]: 

59 """Returns added providers.""" 

60 return self.providers 

61 

62 @property 

63 def random(self) -> random_module.Random: 

64 return self.__random 

65 

66 @random.setter 

67 def random(self, value: random_module.Random) -> None: 

68 self.__random = value 

69 

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 

79 

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 

85 

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) 

91 

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) 

101 

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) 

108 

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. 

115 

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] = {} 

121 

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 

128 

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. 

134 

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) 

142 

143 return result 

144 

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. 

149 

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 

160 

161 return result 

162 

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. 

169 

170 Example: 

171 

172 generator.set_arguments('red_rgb', {'hue': 'red', 'color_format': 'rgb'}) 

173 generator.set_arguments('small', 'max_value', 10) 

174 

175 generator.parse('{{ color:red_rgb }} - {{ pyint:small }}') 

176 """ 

177 return _re_token.sub(self.__format_token, text) 

178 

179 def __format_token(self, matches): 

180 formatter, argument_group = list(matches.groups()) 

181 argument_group = argument_group.lstrip(":").strip() if argument_group else "" 

182 

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}") 

188 

189 formatted = str(self.format(formatter, **arguments)) 

190 else: 

191 formatted = str(self.format(formatter)) 

192 

193 return "".join(formatted)