Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/click/exceptions.py: 32%

117 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import os 

2import typing as t 

3from gettext import gettext as _ 

4from gettext import ngettext 

5 

6from ._compat import get_text_stderr 

7from .utils import echo 

8 

9if t.TYPE_CHECKING: 9 ↛ 10line 9 didn't jump to line 10, because the condition on line 9 was never true

10 from .core import Context 

11 from .core import Parameter 

12 

13 

14def _join_param_hints( 

15 param_hint: t.Optional[t.Union[t.Sequence[str], str]] 

16) -> t.Optional[str]: 

17 if param_hint is not None and not isinstance(param_hint, str): 

18 return " / ".join(repr(x) for x in param_hint) 

19 

20 return param_hint 

21 

22 

23class ClickException(Exception): 

24 """An exception that Click can handle and show to the user.""" 

25 

26 #: The exit code for this exception. 

27 exit_code = 1 

28 

29 def __init__(self, message: str) -> None: 

30 super().__init__(message) 

31 self.message = message 

32 

33 def format_message(self) -> str: 

34 return self.message 

35 

36 def __str__(self) -> str: 

37 return self.message 

38 

39 def show(self, file: t.Optional[t.IO] = None) -> None: 

40 if file is None: 

41 file = get_text_stderr() 

42 

43 echo(_("Error: {message}").format(message=self.format_message()), file=file) 

44 

45 

46class UsageError(ClickException): 

47 """An internal exception that signals a usage error. This typically 

48 aborts any further handling. 

49 

50 :param message: the error message to display. 

51 :param ctx: optionally the context that caused this error. Click will 

52 fill in the context automatically in some situations. 

53 """ 

54 

55 exit_code = 2 

56 

57 def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: 

58 super().__init__(message) 

59 self.ctx = ctx 

60 self.cmd = self.ctx.command if self.ctx else None 

61 

62 def show(self, file: t.Optional[t.IO] = None) -> None: 

63 if file is None: 

64 file = get_text_stderr() 

65 color = None 

66 hint = "" 

67 if ( 

68 self.ctx is not None 

69 and self.ctx.command.get_help_option(self.ctx) is not None 

70 ): 

71 hint = _("Try '{command} {option}' for help.").format( 

72 command=self.ctx.command_path, option=self.ctx.help_option_names[0] 

73 ) 

74 hint = f"{hint}\n" 

75 if self.ctx is not None: 

76 color = self.ctx.color 

77 echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) 

78 echo( 

79 _("Error: {message}").format(message=self.format_message()), 

80 file=file, 

81 color=color, 

82 ) 

83 

84 

85class BadParameter(UsageError): 

86 """An exception that formats out a standardized error message for a 

87 bad parameter. This is useful when thrown from a callback or type as 

88 Click will attach contextual information to it (for instance, which 

89 parameter it is). 

90 

91 .. versionadded:: 2.0 

92 

93 :param param: the parameter object that caused this error. This can 

94 be left out, and Click will attach this info itself 

95 if possible. 

96 :param param_hint: a string that shows up as parameter name. This 

97 can be used as alternative to `param` in cases 

98 where custom validation should happen. If it is 

99 a string it's used as such, if it's a list then 

100 each item is quoted and separated. 

101 """ 

102 

103 def __init__( 

104 self, 

105 message: str, 

106 ctx: t.Optional["Context"] = None, 

107 param: t.Optional["Parameter"] = None, 

108 param_hint: t.Optional[str] = None, 

109 ) -> None: 

110 super().__init__(message, ctx) 

111 self.param = param 

112 self.param_hint = param_hint 

113 

114 def format_message(self) -> str: 

115 if self.param_hint is not None: 

116 param_hint = self.param_hint 

117 elif self.param is not None: 

118 param_hint = self.param.get_error_hint(self.ctx) # type: ignore 

119 else: 

120 return _("Invalid value: {message}").format(message=self.message) 

121 

122 return _("Invalid value for {param_hint}: {message}").format( 

123 param_hint=_join_param_hints(param_hint), message=self.message 

124 ) 

125 

126 

127class MissingParameter(BadParameter): 

128 """Raised if click required an option or argument but it was not 

129 provided when invoking the script. 

130 

131 .. versionadded:: 4.0 

132 

133 :param param_type: a string that indicates the type of the parameter. 

134 The default is to inherit the parameter type from 

135 the given `param`. Valid values are ``'parameter'``, 

136 ``'option'`` or ``'argument'``. 

137 """ 

138 

139 def __init__( 

140 self, 

141 message: t.Optional[str] = None, 

142 ctx: t.Optional["Context"] = None, 

143 param: t.Optional["Parameter"] = None, 

144 param_hint: t.Optional[str] = None, 

145 param_type: t.Optional[str] = None, 

146 ) -> None: 

147 super().__init__(message or "", ctx, param, param_hint) 

148 self.param_type = param_type 

149 

150 def format_message(self) -> str: 

151 if self.param_hint is not None: 

152 param_hint: t.Optional[str] = self.param_hint 

153 elif self.param is not None: 

154 param_hint = self.param.get_error_hint(self.ctx) # type: ignore 

155 else: 

156 param_hint = None 

157 

158 param_hint = _join_param_hints(param_hint) 

159 param_hint = f" {param_hint}" if param_hint else "" 

160 

161 param_type = self.param_type 

162 if param_type is None and self.param is not None: 

163 param_type = self.param.param_type_name 

164 

165 msg = self.message 

166 if self.param is not None: 

167 msg_extra = self.param.type.get_missing_message(self.param) 

168 if msg_extra: 

169 if msg: 

170 msg += f". {msg_extra}" 

171 else: 

172 msg = msg_extra 

173 

174 msg = f" {msg}" if msg else "" 

175 

176 # Translate param_type for known types. 

177 if param_type == "argument": 

178 missing = _("Missing argument") 

179 elif param_type == "option": 

180 missing = _("Missing option") 

181 elif param_type == "parameter": 

182 missing = _("Missing parameter") 

183 else: 

184 missing = _("Missing {param_type}").format(param_type=param_type) 

185 

186 return f"{missing}{param_hint}.{msg}" 

187 

188 def __str__(self) -> str: 

189 if not self.message: 

190 param_name = self.param.name if self.param else None 

191 return _("Missing parameter: {param_name}").format(param_name=param_name) 

192 else: 

193 return self.message 

194 

195 

196class NoSuchOption(UsageError): 

197 """Raised if click attempted to handle an option that does not 

198 exist. 

199 

200 .. versionadded:: 4.0 

201 """ 

202 

203 def __init__( 

204 self, 

205 option_name: str, 

206 message: t.Optional[str] = None, 

207 possibilities: t.Optional[t.Sequence[str]] = None, 

208 ctx: t.Optional["Context"] = None, 

209 ) -> None: 

210 if message is None: 

211 message = _("No such option: {name}").format(name=option_name) 

212 

213 super().__init__(message, ctx) 

214 self.option_name = option_name 

215 self.possibilities = possibilities 

216 

217 def format_message(self) -> str: 

218 if not self.possibilities: 

219 return self.message 

220 

221 possibility_str = ", ".join(sorted(self.possibilities)) 

222 suggest = ngettext( 

223 "Did you mean {possibility}?", 

224 "(Possible options: {possibilities})", 

225 len(self.possibilities), 

226 ).format(possibility=possibility_str, possibilities=possibility_str) 

227 return f"{self.message} {suggest}" 

228 

229 

230class BadOptionUsage(UsageError): 

231 """Raised if an option is generally supplied but the use of the option 

232 was incorrect. This is for instance raised if the number of arguments 

233 for an option is not correct. 

234 

235 .. versionadded:: 4.0 

236 

237 :param option_name: the name of the option being used incorrectly. 

238 """ 

239 

240 def __init__( 

241 self, option_name: str, message: str, ctx: t.Optional["Context"] = None 

242 ) -> None: 

243 super().__init__(message, ctx) 

244 self.option_name = option_name 

245 

246 

247class BadArgumentUsage(UsageError): 

248 """Raised if an argument is generally supplied but the use of the argument 

249 was incorrect. This is for instance raised if the number of values 

250 for an argument is not correct. 

251 

252 .. versionadded:: 6.0 

253 """ 

254 

255 

256class FileError(ClickException): 

257 """Raised if a file cannot be opened.""" 

258 

259 def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: 

260 if hint is None: 

261 hint = _("unknown error") 

262 

263 super().__init__(hint) 

264 self.ui_filename = os.fsdecode(filename) 

265 self.filename = filename 

266 

267 def format_message(self) -> str: 

268 return _("Could not open file {filename!r}: {message}").format( 

269 filename=self.ui_filename, message=self.message 

270 ) 

271 

272 

273class Abort(RuntimeError): 

274 """An internal signalling exception that signals Click to abort.""" 

275 

276 

277class Exit(RuntimeError): 

278 """An exception that indicates that the application should exit with some 

279 status code. 

280 

281 :param code: the status code to exit with. 

282 """ 

283 

284 __slots__ = ("exit_code",) 

285 

286 def __init__(self, code: int = 0) -> None: 

287 self.exit_code = code