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>
diff --git a/tenacity/__init__.py b/tenacity/__init__.py
index c9ea893..9b8b3c5 100644
--- a/tenacity/__init__.py
+++ b/tenacity/__init__.py
@@ -26,8 +26,6 @@
 from concurrent import futures
 from inspect import iscoroutinefunction
 
-from tenacity import _utils
-
 # Import all built-in retry strategies for easier usage.
 from .retry import retry_base  # noqa
 from .retry import retry_all  # noqa
@@ -117,11 +115,8 @@
         def wrap(f: WrappedFn) -> WrappedFn:
             if isinstance(f, retry_base):
                 warnings.warn(
-                    (
-                        "Got retry_base instance ({cls}) as callable argument, "
-                        + "this will probably hang indefinitely (did you mean "
-                        + "retry={cls}(...)?)"
-                    ).format(cls=f.__class__.__name__)
+                    f"Got retry_base instance ({f.__class__.__name__}) as callable argument, "
+                    f"this will probably hang indefinitely (did you mean retry={f.__class__.__name__}(...)?)"
                 )
             if iscoroutinefunction is not None and iscoroutinefunction(f):
                 r: "BaseRetrying" = AsyncRetrying(*dargs, **dkw)
@@ -163,8 +158,8 @@
     NAME: t.Optional[str] = None
 
     def __repr__(self) -> str:
-        state_str = ", ".join("%s=%r" % (field, getattr(self, field)) for field in self.REPR_FIELDS)
-        return "%s(%s)" % (type(self).__name__, state_str)
+        state_str = ", ".join(f"{field}={getattr(self, field)!r}" for field in self.REPR_FIELDS)
+        return f"{self.__class__.__name__}({state_str})"
 
     def __str__(self) -> str:
         return repr(self)
@@ -198,7 +193,7 @@
         raise self
 
     def __str__(self) -> str:
-        return "{0}[{1}]".format(self.__class__.__name__, self.last_attempt)
+        return f"{self.__class__.__name__}[{self.last_attempt}]"
 
 
 class AttemptManager:
@@ -283,15 +278,15 @@
         )
 
     def __repr__(self) -> str:
-        attrs = dict(
-            _utils.visible_attrs(self, attrs={"me": id(self)}),
-            __class__=self.__class__.__name__,
-        )
         return (
-            "<%(__class__)s object at 0x%(me)x (stop=%(stop)s, "
-            "wait=%(wait)s, sleep=%(sleep)s, retry=%(retry)s, "
-            "before=%(before)s, after=%(after)s)>"
-        ) % (attrs)
+            f"<{self.__class__.__name__} object at 0x{id(self):x} ("
+            f"stop={self.stop}, "
+            f"wait={self.wait}, "
+            f"sleep={self.sleep}, "
+            f"retry={self.retry}, "
+            f"before={self.before}, "
+            f"after={self.after})>"
+        )
 
     @property
     def statistics(self) -> t.Dict[str, t.Any]:
diff --git a/tenacity/_utils.py b/tenacity/_utils.py
index 9e2b7f1..d5c4c9d 100644
--- a/tenacity/_utils.py
+++ b/tenacity/_utils.py
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import inspect
 import sys
 import typing
 
@@ -24,19 +23,6 @@
 MAX_WAIT = sys.maxsize / 2
 
 
-def visible_attrs(
-    obj: typing.Any,
-    attrs: typing.Optional[typing.Dict[str, typing.Any]] = None,
-) -> typing.Dict[str, typing.Any]:
-    if attrs is None:
-        attrs = {}
-    for attr_name, attr in inspect.getmembers(obj):
-        if attr_name.startswith("_"):
-            continue
-        attrs[attr_name] = attr
-    return attrs
-
-
 def find_ordinal(pos_num: int) -> str:
     # See: https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers
     if pos_num == 0:
@@ -54,7 +40,7 @@
 
 
 def to_ordinal(pos_num: int) -> str:
-    return "%i%s" % (pos_num, find_ordinal(pos_num))
+    return f"{pos_num}{find_ordinal(pos_num)}"
 
 
 def get_callback_name(cb: typing.Callable[..., typing.Any]) -> str:
diff --git a/tenacity/after.py b/tenacity/after.py
index 97c9407..9dc5572 100644
--- a/tenacity/after.py
+++ b/tenacity/after.py
@@ -39,11 +39,8 @@
         sec = sec_format % _utils.get_callback_name(retry_state.fn)
         logger.log(
             log_level,
-            "Finished call to '{0}' after {1}(s), this was the {2} time calling it.".format(
-                sec,
-                retry_state.seconds_since_start,
-                _utils.to_ordinal(retry_state.attempt_number),
-            ),
+            f"Finished call to '{sec}' after {retry_state.seconds_since_start}(s), "
+            f"this was the {_utils.to_ordinal(retry_state.attempt_number)} time calling it.",
         )
 
     return log_it
diff --git a/tenacity/before.py b/tenacity/before.py
index fd3ea73..6a95406 100644
--- a/tenacity/before.py
+++ b/tenacity/before.py
@@ -34,10 +34,8 @@
     def log_it(retry_state: "RetryCallState") -> None:
         logger.log(
             log_level,
-            "Starting call to '{0}', this is the {1} time calling it.".format(
-                _utils.get_callback_name(retry_state.fn),
-                _utils.to_ordinal(retry_state.attempt_number),
-            ),
+            f"Starting call to '{_utils.get_callback_name(retry_state.fn)}', "
+            f"this is the {_utils.to_ordinal(retry_state.attempt_number)} time calling it.",
         )
 
     return log_it
diff --git a/tenacity/before_sleep.py b/tenacity/before_sleep.py
index e9a332b..44b9f70 100644
--- a/tenacity/before_sleep.py
+++ b/tenacity/before_sleep.py
@@ -38,7 +38,7 @@
     def log_it(retry_state: "RetryCallState") -> None:
         if retry_state.outcome.failed:
             ex = retry_state.outcome.exception()
-            verb, value = "raised", "{0}: {1}".format(type(ex).__name__, ex)
+            verb, value = "raised", f"{ex.__class__.__name__}: {ex}"
 
             if exc_info:
                 local_exc_info = retry_state.outcome.exception()
@@ -50,12 +50,8 @@
 
         logger.log(
             log_level,
-            "Retrying {0} in {1} seconds as it {2} {3}.".format(
-                _utils.get_callback_name(retry_state.fn),
-                getattr(retry_state.next_action, "sleep"),
-                verb,
-                value,
-            ),
+            f"Retrying {_utils.get_callback_name(retry_state.fn)} "
+            f"in {retry_state.next_action.sleep} seconds as it {verb} {value}.",
             exc_info=local_exc_info,
         )
 
diff --git a/tenacity/retry.py b/tenacity/retry.py
index 04db430..dd27117 100644
--- a/tenacity/retry.py
+++ b/tenacity/retry.py
@@ -152,7 +152,7 @@
         match: typing.Optional[str] = None,
     ) -> None:
         if message and match:
-            raise TypeError("{}() takes either 'message' or 'match', not both".format(self.__class__.__name__))
+            raise TypeError(f"{self.__class__.__name__}() takes either 'message' or 'match', not both")
 
         # set predicate
         if message:
@@ -169,7 +169,7 @@
 
             predicate = match_fnc
         else:
-            raise TypeError("{}() missing 1 required argument 'message' or 'match'".format(self.__class__.__name__))
+            raise TypeError(f"{self.__class__.__name__}() missing 1 required argument 'message' or 'match'")
 
         super().__init__(predicate)