File: test_issue_478.py

package info (click to toggle)
python-tenacity 9.1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 700 kB
  • sloc: python: 3,179; makefile: 11
file content (118 lines) | stat: -rw-r--r-- 3,254 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import asyncio
import typing
import unittest

from functools import wraps

from tenacity import RetryCallState, retry


def asynctest(
    callable_: typing.Callable[..., typing.Any],
) -> typing.Callable[..., typing.Any]:
    @wraps(callable_)
    def wrapper(*a: typing.Any, **kw: typing.Any) -> typing.Any:
        loop = asyncio.get_event_loop()
        return loop.run_until_complete(callable_(*a, **kw))

    return wrapper


MAX_RETRY_FIX_ATTEMPTS = 2


class TestIssue478(unittest.TestCase):
    def test_issue(self) -> None:
        results = []

        def do_retry(retry_state: RetryCallState) -> bool:
            outcome = retry_state.outcome
            assert outcome
            ex = outcome.exception()
            _subject_: str = retry_state.args[0]

            if _subject_ == "Fix":  # no retry on fix failure
                return False

            if retry_state.attempt_number >= MAX_RETRY_FIX_ATTEMPTS:
                return False

            if ex:
                do_fix_work()
                return True

            return False

        @retry(reraise=True, retry=do_retry)
        def _do_work(subject: str) -> None:
            if subject == "Error":
                results.append(f"{subject} is not working")
                raise Exception(f"{subject} is not working")
            results.append(f"{subject} is working")

        def do_any_work(subject: str) -> None:
            _do_work(subject)

        def do_fix_work() -> None:
            _do_work("Fix")

        try:
            do_any_work("Error")
        except Exception as exc:
            assert str(exc) == "Error is not working"
        else:
            assert False, "No exception caught"

        assert results == [
            "Error is not working",
            "Fix is working",
            "Error is not working",
        ]

    @asynctest
    async def test_async(self) -> None:
        results = []

        async def do_retry(retry_state: RetryCallState) -> bool:
            outcome = retry_state.outcome
            assert outcome
            ex = outcome.exception()
            _subject_: str = retry_state.args[0]

            if _subject_ == "Fix":  # no retry on fix failure
                return False

            if retry_state.attempt_number >= MAX_RETRY_FIX_ATTEMPTS:
                return False

            if ex:
                await do_fix_work()
                return True

            return False

        @retry(reraise=True, retry=do_retry)
        async def _do_work(subject: str) -> None:
            if subject == "Error":
                results.append(f"{subject} is not working")
                raise Exception(f"{subject} is not working")
            results.append(f"{subject} is working")

        async def do_any_work(subject: str) -> None:
            await _do_work(subject)

        async def do_fix_work() -> None:
            await _do_work("Fix")

        try:
            await do_any_work("Error")
        except Exception as exc:
            assert str(exc) == "Error is not working"
        else:
            assert False, "No exception caught"

        assert results == [
            "Error is not working",
            "Fix is working",
            "Error is not working",
        ]