Skip to content

Commit dc60786

Browse files
Use f-strings instead of str.format as faster and easier to read (#311)
Since python 3.6 we are able to use it. Use attributes in `repr` directly instead of chained construction -> remove unused private helper no-changelog Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent b4d8d6b commit dc60786

File tree

6 files changed

+23
-51
lines changed

6 files changed

+23
-51
lines changed

tenacity/__init__.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
from concurrent import futures
2727
from inspect import iscoroutinefunction
2828

29-
from tenacity import _utils
30-
3129
# Import all built-in retry strategies for easier usage.
3230
from .retry import retry_base # noqa
3331
from .retry import retry_all # noqa
@@ -117,11 +115,8 @@ def retry(*dargs: t.Any, **dkw: t.Any) -> t.Union[WrappedFn, t.Callable[[Wrapped
117115
def wrap(f: WrappedFn) -> WrappedFn:
118116
if isinstance(f, retry_base):
119117
warnings.warn(
120-
(
121-
"Got retry_base instance ({cls}) as callable argument, "
122-
+ "this will probably hang indefinitely (did you mean "
123-
+ "retry={cls}(...)?)"
124-
).format(cls=f.__class__.__name__)
118+
f"Got retry_base instance ({f.__class__.__name__}) as callable argument, "
119+
f"this will probably hang indefinitely (did you mean retry={f.__class__.__name__}(...)?)"
125120
)
126121
if iscoroutinefunction is not None and iscoroutinefunction(f):
127122
r: "BaseRetrying" = AsyncRetrying(*dargs, **dkw)
@@ -163,8 +158,8 @@ class BaseAction:
163158
NAME: t.Optional[str] = None
164159

165160
def __repr__(self) -> str:
166-
state_str = ", ".join("%s=%r" % (field, getattr(self, field)) for field in self.REPR_FIELDS)
167-
return "%s(%s)" % (type(self).__name__, state_str)
161+
state_str = ", ".join(f"{field}={getattr(self, field)!r}" for field in self.REPR_FIELDS)
162+
return f"{self.__class__.__name__}({state_str})"
168163

169164
def __str__(self) -> str:
170165
return repr(self)
@@ -198,7 +193,7 @@ def reraise(self) -> t.NoReturn:
198193
raise self
199194

200195
def __str__(self) -> str:
201-
return "{0}[{1}]".format(self.__class__.__name__, self.last_attempt)
196+
return f"{self.__class__.__name__}[{self.last_attempt}]"
202197

203198

204199
class AttemptManager:
@@ -283,15 +278,15 @@ def copy(
283278
)
284279

285280
def __repr__(self) -> str:
286-
attrs = dict(
287-
_utils.visible_attrs(self, attrs={"me": id(self)}),
288-
__class__=self.__class__.__name__,
289-
)
290281
return (
291-
"<%(__class__)s object at 0x%(me)x (stop=%(stop)s, "
292-
"wait=%(wait)s, sleep=%(sleep)s, retry=%(retry)s, "
293-
"before=%(before)s, after=%(after)s)>"
294-
) % (attrs)
282+
f"<{self.__class__.__name__} object at 0x{id(self):x} ("
283+
f"stop={self.stop}, "
284+
f"wait={self.wait}, "
285+
f"sleep={self.sleep}, "
286+
f"retry={self.retry}, "
287+
f"before={self.before}, "
288+
f"after={self.after})>"
289+
)
295290

296291
@property
297292
def statistics(self) -> t.Dict[str, t.Any]:

tenacity/_utils.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17-
import inspect
1817
import sys
1918
import typing
2019

@@ -24,19 +23,6 @@
2423
MAX_WAIT = sys.maxsize / 2
2524

2625

27-
def visible_attrs(
28-
obj: typing.Any,
29-
attrs: typing.Optional[typing.Dict[str, typing.Any]] = None,
30-
) -> typing.Dict[str, typing.Any]:
31-
if attrs is None:
32-
attrs = {}
33-
for attr_name, attr in inspect.getmembers(obj):
34-
if attr_name.startswith("_"):
35-
continue
36-
attrs[attr_name] = attr
37-
return attrs
38-
39-
4026
def find_ordinal(pos_num: int) -> str:
4127
# See: https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers
4228
if pos_num == 0:
@@ -54,7 +40,7 @@ def find_ordinal(pos_num: int) -> str:
5440

5541

5642
def to_ordinal(pos_num: int) -> str:
57-
return "%i%s" % (pos_num, find_ordinal(pos_num))
43+
return f"{pos_num}{find_ordinal(pos_num)}"
5844

5945

6046
def get_callback_name(cb: typing.Callable[..., typing.Any]) -> str:

tenacity/after.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,8 @@ def log_it(retry_state: "RetryCallState") -> None:
3939
sec = sec_format % _utils.get_callback_name(retry_state.fn)
4040
logger.log(
4141
log_level,
42-
"Finished call to '{0}' after {1}(s), this was the {2} time calling it.".format(
43-
sec,
44-
retry_state.seconds_since_start,
45-
_utils.to_ordinal(retry_state.attempt_number),
46-
),
42+
f"Finished call to '{sec}' after {retry_state.seconds_since_start}(s), "
43+
f"this was the {_utils.to_ordinal(retry_state.attempt_number)} time calling it.",
4744
)
4845

4946
return log_it

tenacity/before.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,8 @@ def before_log(logger: "logging.Logger", log_level: int) -> typing.Callable[["Re
3434
def log_it(retry_state: "RetryCallState") -> None:
3535
logger.log(
3636
log_level,
37-
"Starting call to '{0}', this is the {1} time calling it.".format(
38-
_utils.get_callback_name(retry_state.fn),
39-
_utils.to_ordinal(retry_state.attempt_number),
40-
),
37+
f"Starting call to '{_utils.get_callback_name(retry_state.fn)}', "
38+
f"this is the {_utils.to_ordinal(retry_state.attempt_number)} time calling it.",
4139
)
4240

4341
return log_it

tenacity/before_sleep.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def before_sleep_log(
3838
def log_it(retry_state: "RetryCallState") -> None:
3939
if retry_state.outcome.failed:
4040
ex = retry_state.outcome.exception()
41-
verb, value = "raised", "{0}: {1}".format(type(ex).__name__, ex)
41+
verb, value = "raised", f"{ex.__class__.__name__}: {ex}"
4242

4343
if exc_info:
4444
local_exc_info = retry_state.outcome.exception()
@@ -50,12 +50,8 @@ def log_it(retry_state: "RetryCallState") -> None:
5050

5151
logger.log(
5252
log_level,
53-
"Retrying {0} in {1} seconds as it {2} {3}.".format(
54-
_utils.get_callback_name(retry_state.fn),
55-
getattr(retry_state.next_action, "sleep"),
56-
verb,
57-
value,
58-
),
53+
f"Retrying {_utils.get_callback_name(retry_state.fn)} "
54+
f"in {retry_state.next_action.sleep} seconds as it {verb} {value}.",
5955
exc_info=local_exc_info,
6056
)
6157

tenacity/retry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def __init__(
152152
match: typing.Optional[str] = None,
153153
) -> None:
154154
if message and match:
155-
raise TypeError("{}() takes either 'message' or 'match', not both".format(self.__class__.__name__))
155+
raise TypeError(f"{self.__class__.__name__}() takes either 'message' or 'match', not both")
156156

157157
# set predicate
158158
if message:
@@ -169,7 +169,7 @@ def match_fnc(exception: BaseException) -> bool:
169169

170170
predicate = match_fnc
171171
else:
172-
raise TypeError("{}() missing 1 required argument 'message' or 'match'".format(self.__class__.__name__))
172+
raise TypeError(f"{self.__class__.__name__}() missing 1 required argument 'message' or 'match'")
173173

174174
super().__init__(predicate)
175175

0 commit comments

Comments
 (0)