ci: replace black and flake8 by ruff
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index d06aeec..4bd620f 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -27,14 +27,12 @@
             tox: py310
           - python: "3.11"
             tox: py311
-          - python: "3.11"
-            tox: pep8
-          - python: "3.11"
-            tox: black-ci
-          - python: "3.11"
-            tox: mypy
           - python: "3.12"
             tox: py312
+          - python: "3.12"
+            tox: pep8
+          - python: "3.11"
+            tox: mypy
     steps:
       - name: Checkout 🛎️
         uses: actions/checkout@v4.0.0
diff --git a/.mergify.yml b/.mergify.yml
index 003f217..a9d99e9 100644
--- a/.mergify.yml
+++ b/.mergify.yml
@@ -6,9 +6,7 @@
       - "check-success=test (3.10, py310)"
       - "check-success=test (3.11, py311)"
       - "check-success=test (3.12, py312)"
-      - "check-success=test (3.11, black-ci)"
-      - "check-success=test (3.11, pep8)"
-      - "check-success=test (3.11, mypy)"
+      - "check-success=test (3.12, pep8)"
 
 pull_request_rules:
   - name: warn on no changelog
diff --git a/pyproject.toml b/pyproject.toml
index a293a6a..f4bda94 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,10 +8,10 @@
 ]
 build-backend="setuptools.build_meta"
 
-[tool.black]
-line-length = 120
-safe = true
-target-version = ["py38", "py39", "py310", "py311", "py312"]
+[tool.ruff]
+line-length = 88
+indent-width = 4
+target-version = "py38"
 
 [tool.mypy]
 strict = true
diff --git a/tenacity/__init__.py b/tenacity/__init__.py
index bd60556..11e2faa 100644
--- a/tenacity/__init__.py
+++ b/tenacity/__init__.py
@@ -125,7 +125,9 @@
     NAME: t.Optional[str] = None
 
     def __repr__(self) -> str:
-        state_str = ", ".join(f"{field}={getattr(self, field)!r}" for field in self.REPR_FIELDS)
+        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:
@@ -221,10 +223,14 @@
         retry: t.Union[retry_base, object] = _unset,
         before: t.Union[t.Callable[["RetryCallState"], None], object] = _unset,
         after: t.Union[t.Callable[["RetryCallState"], None], object] = _unset,
-        before_sleep: t.Union[t.Optional[t.Callable[["RetryCallState"], None]], object] = _unset,
+        before_sleep: t.Union[
+            t.Optional[t.Callable[["RetryCallState"], None]], object
+        ] = _unset,
         reraise: t.Union[bool, object] = _unset,
         retry_error_cls: t.Union[t.Type[RetryError], object] = _unset,
-        retry_error_callback: t.Union[t.Optional[t.Callable[["RetryCallState"], t.Any]], object] = _unset,
+        retry_error_callback: t.Union[
+            t.Optional[t.Callable[["RetryCallState"], t.Any]], object
+        ] = _unset,
     ) -> "BaseRetrying":
         """Copy this object with some parameters changed if needed."""
         return self.__class__(
@@ -237,7 +243,9 @@
             before_sleep=_first_set(before_sleep, self.before_sleep),
             reraise=_first_set(reraise, self.reraise),
             retry_error_cls=_first_set(retry_error_cls, self.retry_error_cls),
-            retry_error_callback=_first_set(retry_error_callback, self.retry_error_callback),
+            retry_error_callback=_first_set(
+                retry_error_callback, self.retry_error_callback
+            ),
         )
 
     def __repr__(self) -> str:
@@ -285,7 +293,9 @@
         :param f: A function to wraps for retrying.
         """
 
-        @functools.wraps(f, functools.WRAPPER_ASSIGNMENTS + ("__defaults__", "__kwdefaults__"))
+        @functools.wraps(
+            f, functools.WRAPPER_ASSIGNMENTS + ("__defaults__", "__kwdefaults__")
+        )
         def wrapped_f(*args: t.Any, **kw: t.Any) -> t.Any:
             return self(f, *args, **kw)
 
@@ -414,7 +424,9 @@
         return self.exception() is not None
 
     @classmethod
-    def construct(cls, attempt_number: int, value: t.Any, has_exception: bool) -> "Future":
+    def construct(
+        cls, attempt_number: int, value: t.Any, has_exception: bool
+    ) -> "Future":
         """Construct a new Future object."""
         fut = cls(attempt_number)
         if has_exception:
@@ -477,7 +489,10 @@
         self.outcome, self.outcome_timestamp = fut, ts
 
     def set_exception(
-        self, exc_info: t.Tuple[t.Type[BaseException], BaseException, "types.TracebackType| None"]
+        self,
+        exc_info: t.Tuple[
+            t.Type[BaseException], BaseException, "types.TracebackType| None"
+        ],
     ) -> None:
         ts = time.monotonic()
         fut = Future(self.attempt_number)
@@ -539,7 +554,11 @@
             r: "BaseRetrying"
             if iscoroutinefunction(f):
                 r = AsyncRetrying(*dargs, **dkw)
-            elif tornado and hasattr(tornado.gen, "is_coroutine_function") and tornado.gen.is_coroutine_function(f):
+            elif (
+                tornado
+                and hasattr(tornado.gen, "is_coroutine_function")
+                and tornado.gen.is_coroutine_function(f)
+            ):
                 r = TornadoRetrying(*dargs, **dkw)
             else:
                 r = Retrying(*dargs, **dkw)
diff --git a/tenacity/_asyncio.py b/tenacity/_asyncio.py
index d901cbd..16aec62 100644
--- a/tenacity/_asyncio.py
+++ b/tenacity/_asyncio.py
@@ -33,7 +33,9 @@
 class AsyncRetrying(BaseRetrying):
     sleep: t.Callable[[float], t.Awaitable[t.Any]]
 
-    def __init__(self, sleep: t.Callable[[float], t.Awaitable[t.Any]] = sleep, **kwargs: t.Any) -> None:
+    def __init__(
+        self, sleep: t.Callable[[float], t.Awaitable[t.Any]] = sleep, **kwargs: t.Any
+    ) -> None:
         super().__init__(**kwargs)
         self.sleep = sleep
 
@@ -83,7 +85,9 @@
         fn = super().wraps(fn)
         # Ensure wrapper is recognized as a coroutine function.
 
-        @functools.wraps(fn, functools.WRAPPER_ASSIGNMENTS + ("__defaults__", "__kwdefaults__"))
+        @functools.wraps(
+            fn, functools.WRAPPER_ASSIGNMENTS + ("__defaults__", "__kwdefaults__")
+        )
         async def async_wrapped(*args: t.Any, **kwargs: t.Any) -> t.Any:
             return await fn(*args, **kwargs)
 
diff --git a/tenacity/_utils.py b/tenacity/_utils.py
index f14ff32..67ee0de 100644
--- a/tenacity/_utils.py
+++ b/tenacity/_utils.py
@@ -73,4 +73,6 @@
 
 
 def to_seconds(time_unit: time_unit_type) -> float:
-    return float(time_unit.total_seconds() if isinstance(time_unit, timedelta) else time_unit)
+    return float(
+        time_unit.total_seconds() if isinstance(time_unit, timedelta) else time_unit
+    )
diff --git a/tenacity/before.py b/tenacity/before.py
index 9284f7a..366235a 100644
--- a/tenacity/before.py
+++ b/tenacity/before.py
@@ -28,7 +28,9 @@
     """Before call strategy that does nothing."""
 
 
-def before_log(logger: "logging.Logger", log_level: int) -> typing.Callable[["RetryCallState"], None]:
+def before_log(
+    logger: "logging.Logger", log_level: int
+) -> typing.Callable[["RetryCallState"], None]:
     """Before call strategy that logs to some logger the attempt."""
 
     def log_it(retry_state: "RetryCallState") -> None:
diff --git a/tenacity/before_sleep.py b/tenacity/before_sleep.py
index 279a21e..d04edcf 100644
--- a/tenacity/before_sleep.py
+++ b/tenacity/before_sleep.py
@@ -64,7 +64,8 @@
 
         logger.log(
             log_level,
-            f"Retrying {fn_name} " f"in {retry_state.next_action.sleep} seconds as it {verb} {value}.",
+            f"Retrying {fn_name} "
+            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 765b6fe..c5e55a6 100644
--- a/tenacity/retry.py
+++ b/tenacity/retry.py
@@ -204,7 +204,9 @@
         match: typing.Optional[str] = None,
     ) -> None:
         if message and match:
-            raise TypeError(f"{self.__class__.__name__}() takes either 'message' or 'match', not both")
+            raise TypeError(
+                f"{self.__class__.__name__}() takes either 'message' or 'match', not both"
+            )
 
         # set predicate
         if message:
@@ -221,7 +223,9 @@
 
             predicate = match_fnc
         else:
-            raise TypeError(f"{self.__class__.__name__}() missing 1 required argument 'message' or 'match'")
+            raise TypeError(
+                f"{self.__class__.__name__}() missing 1 required argument 'message' or 'match'"
+            )
 
         super().__init__(predicate)
 
diff --git a/tenacity/stop.py b/tenacity/stop.py
index d7eb6b9..5cda59a 100644
--- a/tenacity/stop.py
+++ b/tenacity/stop.py
@@ -124,4 +124,7 @@
     def __call__(self, retry_state: "RetryCallState") -> bool:
         if retry_state.seconds_since_start is None:
             raise RuntimeError("__call__() called but seconds_since_start is not set")
-        return retry_state.seconds_since_start + retry_state.upcoming_sleep >= self.max_delay
+        return (
+            retry_state.seconds_since_start + retry_state.upcoming_sleep
+            >= self.max_delay
+        )
diff --git a/tenacity/tornadoweb.py b/tenacity/tornadoweb.py
index fabf13a..44323e4 100644
--- a/tenacity/tornadoweb.py
+++ b/tenacity/tornadoweb.py
@@ -29,7 +29,11 @@
 
 
 class TornadoRetrying(BaseRetrying):
-    def __init__(self, sleep: "typing.Callable[[float], Future[None]]" = gen.sleep, **kwargs: typing.Any) -> None:
+    def __init__(
+        self,
+        sleep: "typing.Callable[[float], Future[None]]" = gen.sleep,
+        **kwargs: typing.Any,
+    ) -> None:
         super().__init__(**kwargs)
         self.sleep = sleep
 
diff --git a/tenacity/wait.py b/tenacity/wait.py
index e1e2fe4..3addbb9 100644
--- a/tenacity/wait.py
+++ b/tenacity/wait.py
@@ -41,7 +41,9 @@
         return self.__add__(other)
 
 
-WaitBaseT = typing.Union[wait_base, typing.Callable[["RetryCallState"], typing.Union[float, int]]]
+WaitBaseT = typing.Union[
+    wait_base, typing.Callable[["RetryCallState"], typing.Union[float, int]]
+]
 
 
 class wait_fixed(wait_base):
@@ -64,12 +66,16 @@
 class wait_random(wait_base):
     """Wait strategy that waits a random amount of time between min/max."""
 
-    def __init__(self, min: _utils.time_unit_type = 0, max: _utils.time_unit_type = 1) -> None:  # noqa
+    def __init__(
+        self, min: _utils.time_unit_type = 0, max: _utils.time_unit_type = 1
+    ) -> None:  # noqa
         self.wait_random_min = _utils.to_seconds(min)
         self.wait_random_max = _utils.to_seconds(max)
 
     def __call__(self, retry_state: "RetryCallState") -> float:
-        return self.wait_random_min + (random.random() * (self.wait_random_max - self.wait_random_min))
+        return self.wait_random_min + (
+            random.random() * (self.wait_random_max - self.wait_random_min)
+        )
 
 
 class wait_combine(wait_base):
diff --git a/tests/test_after.py b/tests/test_after.py
index 3211703..0cb4f71 100644
--- a/tests/test_after.py
+++ b/tests/test_after.py
@@ -11,7 +11,15 @@
 
 class TestAfterLogFormat(unittest.TestCase):
     def setUp(self) -> None:
-        self.log_level = random.choice((logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL))
+        self.log_level = random.choice(
+            (
+                logging.DEBUG,
+                logging.INFO,
+                logging.WARNING,
+                logging.ERROR,
+                logging.CRITICAL,
+            )
+        )
         self.previous_attempt_number = random.randint(1, 512)
 
     def test_01_default(self):
@@ -22,10 +30,18 @@
         sec_format = "%0.3f"
         delay_since_first_attempt = 0.1
 
-        retry_state = test_tenacity.make_retry_state(self.previous_attempt_number, delay_since_first_attempt)
-        fun = after_log(logger=logger, log_level=self.log_level)  # use default sec_format
+        retry_state = test_tenacity.make_retry_state(
+            self.previous_attempt_number, delay_since_first_attempt
+        )
+        fun = after_log(
+            logger=logger, log_level=self.log_level
+        )  # use default sec_format
         fun(retry_state)
-        fn_name = "<unknown>" if retry_state.fn is None else _utils.get_callback_name(retry_state.fn)
+        fn_name = (
+            "<unknown>"
+            if retry_state.fn is None
+            else _utils.get_callback_name(retry_state.fn)
+        )
         log.assert_called_once_with(
             self.log_level,
             f"Finished call to '{fn_name}' "
@@ -41,10 +57,16 @@
         sec_format = "%.1f"
         delay_since_first_attempt = 0.1
 
-        retry_state = test_tenacity.make_retry_state(self.previous_attempt_number, delay_since_first_attempt)
+        retry_state = test_tenacity.make_retry_state(
+            self.previous_attempt_number, delay_since_first_attempt
+        )
         fun = after_log(logger=logger, log_level=self.log_level, sec_format=sec_format)
         fun(retry_state)
-        fn_name = "<unknown>" if retry_state.fn is None else _utils.get_callback_name(retry_state.fn)
+        fn_name = (
+            "<unknown>"
+            if retry_state.fn is None
+            else _utils.get_callback_name(retry_state.fn)
+        )
         log.assert_called_once_with(
             self.log_level,
             f"Finished call to '{fn_name}' "
diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py
index 542f540..24cf6ed 100644
--- a/tests/test_asyncio.py
+++ b/tests/test_asyncio.py
@@ -96,12 +96,19 @@
         async def function_with_kwdefaults(*, a=1):
             return a
 
-        retrying = AsyncRetrying(wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3))
+        retrying = AsyncRetrying(
+            wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3)
+        )
         wrapped_defaults_function = retrying.wraps(function_with_defaults)
         wrapped_kwdefaults_function = retrying.wraps(function_with_kwdefaults)
 
-        self.assertEqual(function_with_defaults.__defaults__, wrapped_defaults_function.__defaults__)
-        self.assertEqual(function_with_kwdefaults.__kwdefaults__, wrapped_kwdefaults_function.__kwdefaults__)
+        self.assertEqual(
+            function_with_defaults.__defaults__, wrapped_defaults_function.__defaults__
+        )
+        self.assertEqual(
+            function_with_kwdefaults.__kwdefaults__,
+            wrapped_kwdefaults_function.__kwdefaults__,
+        )
 
     @asynctest
     async def test_attempt_number_is_correct_for_interleaved_coroutines(self):
@@ -152,7 +159,9 @@
             pass
 
         try:
-            async for attempt in tasyncio.AsyncRetrying(stop=stop_after_attempt(1), reraise=True):
+            async for attempt in tasyncio.AsyncRetrying(
+                stop=stop_after_attempt(1), reraise=True
+            ):
                 with attempt:
                     raise CustomError()
         except CustomError:
@@ -164,7 +173,9 @@
     async def test_sleeps(self):
         start = current_time_ms()
         try:
-            async for attempt in tasyncio.AsyncRetrying(stop=stop_after_attempt(1), wait=wait_fixed(1)):
+            async for attempt in tasyncio.AsyncRetrying(
+                stop=stop_after_attempt(1), wait=wait_fixed(1)
+            ):
                 with attempt:
                     raise Exception()
         except RetryError:
diff --git a/tests/test_tenacity.py b/tests/test_tenacity.py
index ac79201..e158fa6 100644
--- a/tests/test_tenacity.py
+++ b/tests/test_tenacity.py
@@ -51,12 +51,19 @@
     assert retry_state.seconds_since_start == delay
 
 
-def make_retry_state(previous_attempt_number, delay_since_first_attempt, last_result=None, upcoming_sleep=0):
+def make_retry_state(
+    previous_attempt_number,
+    delay_since_first_attempt,
+    last_result=None,
+    upcoming_sleep=0,
+):
     """Construct RetryCallState for given attempt number & delay.
 
     Only used in testing and thus is extra careful about timestamp arithmetics.
     """
-    required_parameter_unset = previous_attempt_number is _unset or delay_since_first_attempt is _unset
+    required_parameter_unset = (
+        previous_attempt_number is _unset or delay_since_first_attempt is _unset
+    )
     if required_parameter_unset:
         raise _make_unset_exception(
             "wait/stop",
@@ -90,9 +97,15 @@
         rs.idle_for = 1.1111111
         assert repr(rs).endswith("attempt #1; slept for 1.11; last result: none yet>")
         rs = make_retry_state(2, 5)
-        assert repr(rs).endswith("attempt #2; slept for 0.0; last result: returned None>")
-        rs = make_retry_state(0, 0, last_result=tenacity.Future.construct(1, ValueError("aaa"), True))
-        assert repr(rs).endswith("attempt #0; slept for 0.0; last result: failed (ValueError aaa)>")
+        assert repr(rs).endswith(
+            "attempt #2; slept for 0.0; last result: returned None>"
+        )
+        rs = make_retry_state(
+            0, 0, last_result=tenacity.Future.construct(1, ValueError("aaa"), True)
+        )
+        assert repr(rs).endswith(
+            "attempt #0; slept for 0.0; last result: failed (ValueError aaa)>"
+        )
 
 
 class TestStopConditions(unittest.TestCase):
@@ -101,7 +114,9 @@
         self.assertFalse(r.stop(make_retry_state(3, 6546)))
 
     def test_stop_any(self):
-        stop = tenacity.stop_any(tenacity.stop_after_delay(1), tenacity.stop_after_attempt(4))
+        stop = tenacity.stop_any(
+            tenacity.stop_after_delay(1), tenacity.stop_after_attempt(4)
+        )
 
         def s(*args):
             return stop(make_retry_state(*args))
@@ -114,7 +129,9 @@
         self.assertTrue(s(4, 1.8))
 
     def test_stop_all(self):
-        stop = tenacity.stop_all(tenacity.stop_after_delay(1), tenacity.stop_after_attempt(4))
+        stop = tenacity.stop_all(
+            tenacity.stop_after_delay(1), tenacity.stop_after_attempt(4)
+        )
 
         def s(*args):
             return stop(make_retry_state(*args))
@@ -170,7 +187,9 @@
         for delay in (1, datetime.timedelta(seconds=1)):
             with self.subTest():
                 r = Retrying(stop=tenacity.stop_before_delay(delay))
-                self.assertFalse(r.stop(make_retry_state(2, 0.999, upcoming_sleep=0.0001)))
+                self.assertFalse(
+                    r.stop(make_retry_state(2, 0.999, upcoming_sleep=0.0001))
+                )
                 self.assertTrue(r.stop(make_retry_state(2, 1, upcoming_sleep=0.001)))
                 self.assertTrue(r.stop(make_retry_state(2, 1, upcoming_sleep=1)))
 
@@ -205,15 +224,23 @@
                 self.assertEqual(1, r.wait(make_retry_state(12, 6546)))
 
     def test_incrementing_sleep(self):
-        for start, increment in ((500, 100), (datetime.timedelta(seconds=500), datetime.timedelta(seconds=100))):
+        for start, increment in (
+            (500, 100),
+            (datetime.timedelta(seconds=500), datetime.timedelta(seconds=100)),
+        ):
             with self.subTest():
-                r = Retrying(wait=tenacity.wait_incrementing(start=start, increment=increment))
+                r = Retrying(
+                    wait=tenacity.wait_incrementing(start=start, increment=increment)
+                )
                 self.assertEqual(500, r.wait(make_retry_state(1, 6546)))
                 self.assertEqual(600, r.wait(make_retry_state(2, 6546)))
                 self.assertEqual(700, r.wait(make_retry_state(3, 6546)))
 
     def test_random_sleep(self):
-        for min_, max_ in ((1, 20), (datetime.timedelta(seconds=1), datetime.timedelta(seconds=20))):
+        for min_, max_ in (
+            (1, 20),
+            (datetime.timedelta(seconds=1), datetime.timedelta(seconds=20)),
+        ):
             with self.subTest():
                 r = Retrying(wait=tenacity.wait_random(min=min_, max=max_))
                 times = set()
@@ -300,7 +327,10 @@
         self.assertEqual(r.wait(make_retry_state(20, 0)), 1048576)
 
     def test_exponential_with_min_wait_andmax__wait(self):
-        for min_, max_ in ((10, 100), (datetime.timedelta(seconds=10), datetime.timedelta(seconds=100))):
+        for min_, max_ in (
+            (10, 100),
+            (datetime.timedelta(seconds=10), datetime.timedelta(seconds=100)),
+        ):
             with self.subTest():
                 r = Retrying(wait=tenacity.wait_exponential(min=min_, max=max_))
                 self.assertEqual(r.wait(make_retry_state(1, 0)), 10)
@@ -327,7 +357,11 @@
         self.assertEqual(r.wait(make_retry_state(10, 100)), 1000)
 
     def test_wait_combine(self):
-        r = Retrying(wait=tenacity.wait_combine(tenacity.wait_random(0, 3), tenacity.wait_fixed(5)))
+        r = Retrying(
+            wait=tenacity.wait_combine(
+                tenacity.wait_random(0, 3), tenacity.wait_fixed(5)
+            )
+        )
         # Test it a few time since it's random
         for i in range(1000):
             w = r.wait(make_retry_state(1, 5))
@@ -343,7 +377,11 @@
             self.assertGreaterEqual(w, 5)
 
     def test_wait_triple_sum(self):
-        r = Retrying(wait=tenacity.wait_fixed(1) + tenacity.wait_random(0, 3) + tenacity.wait_fixed(5))
+        r = Retrying(
+            wait=tenacity.wait_fixed(1)
+            + tenacity.wait_random(0, 3)
+            + tenacity.wait_fixed(5)
+        )
         # Test it a few time since it's random
         for i in range(1000):
             w = r.wait(make_retry_state(1, 5))
@@ -495,7 +533,10 @@
 
         retrying = Retrying(
             wait=waitfunc,
-            retry=(tenacity.retry_if_exception_type() | tenacity.retry_if_result(lambda result: result == 123)),
+            retry=(
+                tenacity.retry_if_exception_type()
+                | tenacity.retry_if_result(lambda result: result == 123)
+            ),
         )
 
         def returnval():
@@ -579,7 +620,9 @@
         self.assertFalse(r(tenacity.Future.construct(1, 1, True)))
 
     def test_retry_and(self):
-        retry = tenacity.retry_if_result(lambda x: x == 1) & tenacity.retry_if_result(lambda x: isinstance(x, int))
+        retry = tenacity.retry_if_result(lambda x: x == 1) & tenacity.retry_if_result(
+            lambda x: isinstance(x, int)
+        )
 
         def r(fut):
             retry_state = make_retry_state(1, 1.0, last_result=fut)
@@ -591,7 +634,9 @@
         self.assertFalse(r(tenacity.Future.construct(1, 1, True)))
 
     def test_retry_or(self):
-        retry = tenacity.retry_if_result(lambda x: x == "foo") | tenacity.retry_if_result(lambda x: isinstance(x, int))
+        retry = tenacity.retry_if_result(
+            lambda x: x == "foo"
+        ) | tenacity.retry_if_result(lambda x: isinstance(x, int))
 
         def r(fut):
             retry_state = make_retry_state(1, 1.0, last_result=fut)
@@ -609,7 +654,9 @@
 
     def test_retry_try_again(self):
         self._attempts = 0
-        Retrying(stop=tenacity.stop_after_attempt(5), retry=tenacity.retry_never)(self._raise_try_again)
+        Retrying(stop=tenacity.stop_after_attempt(5), retry=tenacity.retry_never)(
+            self._raise_try_again
+        )
         self.assertEqual(3, self._attempts)
 
     def test_retry_try_again_forever(self):
@@ -867,7 +914,9 @@
     return thing.go()
 
 
-@retry(stop=tenacity.stop_after_attempt(3), retry=tenacity.retry_if_exception_type(IOError))
+@retry(
+    stop=tenacity.stop_after_attempt(3), retry=tenacity.retry_if_exception_type(IOError)
+)
 def _retryable_test_with_exception_type_io_attempt_limit(thing):
     return thing.go()
 
@@ -892,28 +941,46 @@
 
 @retry(
     stop=tenacity.stop_after_attempt(5),
-    retry=tenacity.retry_if_exception_message(message=NoCustomErrorAfterCount.derived_message),
+    retry=tenacity.retry_if_exception_message(
+        message=NoCustomErrorAfterCount.derived_message
+    ),
 )
 def _retryable_test_if_exception_message_message(thing):
     return thing.go()
 
 
-@retry(retry=tenacity.retry_if_not_exception_message(message=NoCustomErrorAfterCount.derived_message))
+@retry(
+    retry=tenacity.retry_if_not_exception_message(
+        message=NoCustomErrorAfterCount.derived_message
+    )
+)
 def _retryable_test_if_not_exception_message_message(thing):
     return thing.go()
 
 
-@retry(retry=tenacity.retry_if_exception_message(match=NoCustomErrorAfterCount.derived_message[:3] + ".*"))
+@retry(
+    retry=tenacity.retry_if_exception_message(
+        match=NoCustomErrorAfterCount.derived_message[:3] + ".*"
+    )
+)
 def _retryable_test_if_exception_message_match(thing):
     return thing.go()
 
 
-@retry(retry=tenacity.retry_if_not_exception_message(match=NoCustomErrorAfterCount.derived_message[:3] + ".*"))
+@retry(
+    retry=tenacity.retry_if_not_exception_message(
+        match=NoCustomErrorAfterCount.derived_message[:3] + ".*"
+    )
+)
 def _retryable_test_if_not_exception_message_match(thing):
     return thing.go()
 
 
-@retry(retry=tenacity.retry_if_not_exception_message(message=NameErrorUntilCount.derived_message))
+@retry(
+    retry=tenacity.retry_if_not_exception_message(
+        message=NameErrorUntilCount.derived_message
+    )
+)
 def _retryable_test_not_exception_message_delay(thing):
     return thing.go()
 
@@ -977,7 +1044,9 @@
             self.assertTrue(isinstance(n, NameError))
             print(n)
 
-        self.assertTrue(_retryable_test_with_exception_type_custom(NoCustomErrorAfterCount(5)))
+        self.assertTrue(
+            _retryable_test_with_exception_type_custom(NoCustomErrorAfterCount(5))
+        )
 
         try:
             _retryable_test_with_exception_type_custom(NoNameErrorAfterCount(5))
@@ -987,7 +1056,9 @@
             print(n)
 
     def test_retry_except_exception_of_type(self):
-        self.assertTrue(_retryable_test_if_not_exception_type_io(NoNameErrorAfterCount(5)))
+        self.assertTrue(
+            _retryable_test_if_not_exception_type_io(NoNameErrorAfterCount(5))
+        )
 
         try:
             _retryable_test_if_not_exception_type_io(NoIOErrorAfterCount(5))
@@ -998,7 +1069,9 @@
 
     def test_retry_until_exception_of_type_attempt_number(self):
         try:
-            self.assertTrue(_retryable_test_with_unless_exception_type_name(NameErrorUntilCount(5)))
+            self.assertTrue(
+                _retryable_test_with_unless_exception_type_name(NameErrorUntilCount(5))
+            )
         except NameError as e:
             s = _retryable_test_with_unless_exception_type_name.retry.statistics
             self.assertTrue(s["attempt_number"] == 6)
@@ -1009,7 +1082,11 @@
     def test_retry_until_exception_of_type_no_type(self):
         try:
             # no input should catch all subclasses of Exception
-            self.assertTrue(_retryable_test_with_unless_exception_type_no_input(NameErrorUntilCount(5)))
+            self.assertTrue(
+                _retryable_test_with_unless_exception_type_no_input(
+                    NameErrorUntilCount(5)
+                )
+            )
         except NameError as e:
             s = _retryable_test_with_unless_exception_type_no_input.retry.statistics
             self.assertTrue(s["attempt_number"] == 6)
@@ -1020,7 +1097,9 @@
     def test_retry_until_exception_of_type_wrong_exception(self):
         try:
             # two iterations with IOError, one that returns True
-            _retryable_test_with_unless_exception_type_name_attempt_limit(IOErrorUntilCount(2))
+            _retryable_test_with_unless_exception_type_name_attempt_limit(
+                IOErrorUntilCount(2)
+            )
             self.fail("Expected RetryError")
         except RetryError as e:
             self.assertTrue(isinstance(e, RetryError))
@@ -1028,21 +1107,29 @@
 
     def test_retry_if_exception_message(self):
         try:
-            self.assertTrue(_retryable_test_if_exception_message_message(NoCustomErrorAfterCount(3)))
+            self.assertTrue(
+                _retryable_test_if_exception_message_message(NoCustomErrorAfterCount(3))
+            )
         except CustomError:
             print(_retryable_test_if_exception_message_message.retry.statistics)
             self.fail("CustomError should've been retried from errormessage")
 
     def test_retry_if_not_exception_message(self):
         try:
-            self.assertTrue(_retryable_test_if_not_exception_message_message(NoCustomErrorAfterCount(2)))
+            self.assertTrue(
+                _retryable_test_if_not_exception_message_message(
+                    NoCustomErrorAfterCount(2)
+                )
+            )
         except CustomError:
             s = _retryable_test_if_not_exception_message_message.retry.statistics
             self.assertTrue(s["attempt_number"] == 1)
 
     def test_retry_if_not_exception_message_delay(self):
         try:
-            self.assertTrue(_retryable_test_not_exception_message_delay(NameErrorUntilCount(3)))
+            self.assertTrue(
+                _retryable_test_not_exception_message_delay(NameErrorUntilCount(3))
+            )
         except NameError:
             s = _retryable_test_not_exception_message_delay.retry.statistics
             print(s["attempt_number"])
@@ -1050,19 +1137,27 @@
 
     def test_retry_if_exception_message_match(self):
         try:
-            self.assertTrue(_retryable_test_if_exception_message_match(NoCustomErrorAfterCount(3)))
+            self.assertTrue(
+                _retryable_test_if_exception_message_match(NoCustomErrorAfterCount(3))
+            )
         except CustomError:
             self.fail("CustomError should've been retried from errormessage")
 
     def test_retry_if_not_exception_message_match(self):
         try:
-            self.assertTrue(_retryable_test_if_not_exception_message_message(NoCustomErrorAfterCount(2)))
+            self.assertTrue(
+                _retryable_test_if_not_exception_message_message(
+                    NoCustomErrorAfterCount(2)
+                )
+            )
         except CustomError:
             s = _retryable_test_if_not_exception_message_message.retry.statistics
             self.assertTrue(s["attempt_number"] == 1)
 
     def test_retry_if_exception_cause_type(self):
-        self.assertTrue(_retryable_test_with_exception_cause_type(NoNameErrorCauseAfterCount(5)))
+        self.assertTrue(
+            _retryable_test_with_exception_cause_type(NoNameErrorCauseAfterCount(5))
+        )
 
         try:
             _retryable_test_with_exception_cause_type(NoIOErrorCauseAfterCount(5))
@@ -1077,12 +1172,19 @@
         def function_with_kwdefaults(*, a=1):
             return a
 
-        retrying = Retrying(wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3))
+        retrying = Retrying(
+            wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3)
+        )
         wrapped_defaults_function = retrying.wraps(function_with_defaults)
         wrapped_kwdefaults_function = retrying.wraps(function_with_kwdefaults)
 
-        self.assertEqual(function_with_defaults.__defaults__, wrapped_defaults_function.__defaults__)
-        self.assertEqual(function_with_kwdefaults.__kwdefaults__, wrapped_kwdefaults_function.__kwdefaults__)
+        self.assertEqual(
+            function_with_defaults.__defaults__, wrapped_defaults_function.__defaults__
+        )
+        self.assertEqual(
+            function_with_kwdefaults.__kwdefaults__,
+            wrapped_kwdefaults_function.__kwdefaults__,
+        )
 
     def test_defaults(self):
         self.assertTrue(_retryable_default(NoNameErrorAfterCount(5)))
@@ -1101,7 +1203,9 @@
             def __call__(self):
                 return "Hello"
 
-        retrying = Retrying(wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3))
+        retrying = Retrying(
+            wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3)
+        )
         h = retrying.wraps(Hello())
         self.assertEqual(h(), "Hello")
 
@@ -1109,13 +1213,17 @@
 class TestRetryWith:
     def test_redefine_wait(self):
         start = current_time_ms()
-        result = _retryable_test_with_wait.retry_with(wait=tenacity.wait_fixed(0.1))(NoneReturnUntilAfterCount(5))
+        result = _retryable_test_with_wait.retry_with(wait=tenacity.wait_fixed(0.1))(
+            NoneReturnUntilAfterCount(5)
+        )
         t = current_time_ms() - start
         assert t >= 500
         assert result is True
 
     def test_redefine_stop(self):
-        result = _retryable_test_with_stop.retry_with(stop=tenacity.stop_after_attempt(5))(NoneReturnUntilAfterCount(4))
+        result = _retryable_test_with_stop.retry_with(
+            stop=tenacity.stop_after_attempt(5)
+        )(NoneReturnUntilAfterCount(4))
         assert result is True
 
     def test_retry_error_cls_should_be_preserved(self):
@@ -1220,7 +1328,10 @@
         finally:
             logger.removeHandler(handler)
 
-        etalon_re = r"^Retrying .* in 0\.01 seconds as it raised " r"(IO|OS)Error: Hi there, I'm an IOError\.$"
+        etalon_re = (
+            r"^Retrying .* in 0\.01 seconds as it raised "
+            r"(IO|OS)Error: Hi there, I'm an IOError\.$"
+        )
         self.assertEqual(len(handler.records), 2)
         fmt = logging.Formatter().format
         self.assertRegex(fmt(handler.records[0]), etalon_re)
@@ -1237,7 +1348,9 @@
         handler = CapturingHandler()
         logger.addHandler(handler)
         try:
-            _before_sleep = tenacity.before_sleep_log(logger, logging.INFO, exc_info=True)
+            _before_sleep = tenacity.before_sleep_log(
+                logger, logging.INFO, exc_info=True
+            )
             retrying = Retrying(
                 wait=tenacity.wait_fixed(0.01),
                 stop=tenacity.stop_after_attempt(3),
@@ -1267,7 +1380,9 @@
         handler = CapturingHandler()
         logger.addHandler(handler)
         try:
-            _before_sleep = tenacity.before_sleep_log(logger, logging.INFO, exc_info=exc_info)
+            _before_sleep = tenacity.before_sleep_log(
+                logger, logging.INFO, exc_info=exc_info
+            )
             _retry = tenacity.retry_if_result(lambda result: result is None)
             retrying = Retrying(
                 wait=tenacity.wait_fixed(0.01),
@@ -1550,7 +1665,9 @@
 
 
 class TestRetryTyping(unittest.TestCase):
-    @pytest.mark.skipif(sys.version_info < (3, 0), reason="typeguard not supported for python 2")
+    @pytest.mark.skipif(
+        sys.version_info < (3, 0), reason="typeguard not supported for python 2"
+    )
     def test_retry_type_annotations(self):
         """The decorator should maintain types of decorated functions."""
         # Just in case this is run with unit-test, return early for py2
diff --git a/tox.ini b/tox.ini
index 108c6e2..13e5a1d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -15,20 +15,10 @@
 
 [testenv:pep8]
 basepython = python3
-deps = flake8
-       flake8-import-order
-       flake8-blind-except
-       flake8-builtins
-       flake8-docstrings
-       flake8-rst-docstrings
-       flake8-logging-format
-commands = flake8 {posargs}
-
-[testenv:black]
-deps =
-    black
+deps = ruff
 commands =
-    black .
+  ruff check . {posargs}
+  ruff format --check . {posargs}
 
 [testenv:mypy]
 deps =
@@ -37,21 +27,7 @@
 commands =
     mypy {posargs}
 
-[testenv:black-ci]
-deps =
-    black
-    {[testenv:black]deps}
-commands =
-    black --check --diff .
-
 [testenv:reno]
 basepython = python3
 deps = reno
-commands = reno {posargs}
-
-[flake8]
-exclude = .tox,.eggs
-show-source = true
-ignore = D100,D101,D102,D103,D104,D105,D107,G200,G201,W503,W504,E501
-enable-extensions=G
-max-line-length = 120
+commands = reno {posargs}
\ No newline at end of file