1# Copyright 2016 Julien Danjou
2# Copyright 2016 Joshua Harlow
3# Copyright 2013-2014 Ray Holder
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import typing
18
19from tenacity import _utils
20
21if typing.TYPE_CHECKING:
22 from tenacity import RetryCallState
23
24
25def before_sleep_nothing(retry_state: "RetryCallState") -> None:
26 """Before sleep strategy that does nothing."""
27
28
29def before_sleep_log(
30 logger: _utils.LoggerProtocol,
31 log_level: int,
32 exc_info: bool = False,
33 sec_format: str = "%.3g",
34) -> typing.Callable[["RetryCallState"], None]:
35 """Before sleep strategy that logs to some logger the attempt."""
36
37 def log_it(retry_state: "RetryCallState") -> None:
38 local_exc_info: BaseException | bool | None
39
40 if retry_state.outcome is None:
41 raise RuntimeError("log_it() called before outcome was set")
42
43 if retry_state.next_action is None:
44 raise RuntimeError("log_it() called before next_action was set")
45
46 if retry_state.outcome.failed:
47 ex = retry_state.outcome.exception()
48 verb, value = "raised", f"{ex.__class__.__name__}: {ex}"
49
50 if exc_info:
51 local_exc_info = retry_state.outcome.exception()
52 else:
53 local_exc_info = False
54 else:
55 verb, value = "returned", retry_state.outcome.result()
56 local_exc_info = False # exc_info does not apply when no exception
57
58 if retry_state.fn is None:
59 # NOTE(sileht): can't really happen, but we must please mypy
60 fn_name = "<unknown>"
61 else:
62 fn_name = _utils.get_callback_name(retry_state.fn)
63
64 logger.log(
65 log_level,
66 f"Retrying {fn_name} "
67 f"in {sec_format % retry_state.next_action.sleep} seconds as it {verb} {value}.",
68 exc_info=local_exc_info,
69 )
70
71 return log_it