This repository was archived by the owner on Aug 8, 2025. It is now read-only.
  
  
  - 
                Notifications
    
You must be signed in to change notification settings  - Fork 157
 
drop python<=3.7 support #219
          
     Open
      
      
            kloczek
  wants to merge
  4
  commits into
  litl:master
  
    
      
        
          
  
    
      Choose a base branch
      
     
    
      
        
      
      
        
          
          
        
        
          
            
              
              
              
  
           
        
        
          
            
              
              
           
        
       
     
  
        
          
            
          
            
          
        
       
    
      
from
kloczek:master
  
      
      
   
  
    
  
  
  
 
  
      
    base: master
Could not load branches
            
              
  
    Branch not found: {{ refName }}
  
            
                
      Loading
              
            Could not load tags
            
            
              Nothing to show
            
              
  
            
                
      Loading
              
            Are you sure you want to change the base?
            Some commits from the old base branch may be removed from the timeline,
            and old review comments may become outdated.
          
          
                
     Open
            
            
          Conversation
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
    According to https://endoflife.date/python python 3.7 has been EOSed 27 Jun 2023. Filter all code over `pyupgracde --py38-plus`. Signed-off-by: Tomasz Kłoczko <kloczek@github.com>
Signed-off-by: Tomasz Kłoczko <kloczek@github.com>
| 
           from whole patch generated by  --- a/backoff/_wait_gen.py
+++ b/backoff/_wait_gen.py
@@ -71,8 +69,7 @@
     else:
         itr = iter(interval)  # type: ignore
-    for val in itr:
-        yield val
+    yield from itr
 def runtime(Because after that pytest fails with: pytest output:+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-backoff-2.2.1-2.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-backoff-2.2.1-2.fc37.x86_64/usr/lib/python3.10/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.10.14, pytest-8.2.2, pluggy-1.5.0
rootdir: /home/tkloczko/rpmbuild/BUILD/backoff-2.2.1
configfile: pyproject.toml
plugins: asyncio-0.23.8
asyncio: mode=strict
collected 119 items
tests/test_backoff.py ........F..FFFFF..FFFF..F.......................................................                                                                                [ 67%]
tests/test_backoff_async.py .......F..FFFFFF..FFFFF....                                                                                                                               [ 89%]
tests/test_integration.py ..                                                                                                                                                          [ 91%]
tests/test_jitter.py .                                                                                                                                                                [ 92%]
tests/test_wait_gen.py .........                                                                                                                                                      [100%]
========================================================================================= FAILURES ==========================================================================================
____________________________________________________________________________ test_on_exception_constant_iterable ____________________________________________________________________________
    @backoff.on_exception(
        backoff.constant,
        KeyError,
        interval=(1, 2, 3),
        on_backoff=backoffs.append,
        on_giveup=giveups.append,
        on_success=successes.append,
    )
    def endless_exceptions():
>       raise KeyError('foo')
E       KeyError: 'foo'
tests/test_backoff.py:205: KeyError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29997f10>
    def test_on_exception_constant_iterable(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        backoffs = []
        giveups = []
        successes = []
        @backoff.on_exception(
            backoff.constant,
            KeyError,
            interval=(1, 2, 3),
            on_backoff=backoffs.append,
            on_giveup=giveups.append,
            on_success=successes.append,
        )
        def endless_exceptions():
            raise KeyError('foo')
        with pytest.raises(KeyError):
>           endless_exceptions()
tests/test_backoff.py:208:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = (1, 2, 3)
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'tuple_iterator' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off endless_exceptions(...) for 0.8s (KeyError: 'foo')
_________________________________________________________________________________ test_on_exception_success _________________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          Exception,
                          on_success=successes.append,
                          on_backoff=backoffs.append,
                          on_giveup=giveups.append,
                          jitter=None,
                          interval=0)
    @_save_target
    def succeeder(*args, **kwargs):
        # succeed after we've backed off twice
        if len(backoffs) < 2:
>           raise ValueError("catch me")
E           ValueError: catch me
tests/test_backoff.py:289: ValueError
During handling of the above exception, another exception occurred:
    def test_on_exception_success():
        backoffs, giveups, successes = [], [], []
        @backoff.on_exception(backoff.constant,
                              Exception,
                              on_success=successes.append,
                              on_backoff=backoffs.append,
                              on_giveup=giveups.append,
                              jitter=None,
                              interval=0)
        @_save_target
        def succeeder(*args, **kwargs):
            # succeed after we've backed off twice
            if len(backoffs) < 2:
                raise ValueError("catch me")
>       succeeder(1, 2, 3, foo=1, bar=2)
tests/test_backoff.py:291:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off succeeder(...) for 0.0s (ValueError: catch me)
______________________________________________________________________________ test_on_exception_giveup[True] _______________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          on_success=successes.append,
                          on_backoff=backoffs.append,
                          on_giveup=giveups.append,
                          max_tries=3,
                          jitter=None,
                          raise_on_giveup=raise_on_giveup,
                          interval=0)
    @_save_target
    def exceptor(*args, **kwargs):
>       raise ValueError("catch me")
E       ValueError: catch me
tests/test_backoff.py:334: ValueError
During handling of the above exception, another exception occurred:
raise_on_giveup = True
    @pytest.mark.parametrize('raise_on_giveup', [True, False])
    def test_on_exception_giveup(raise_on_giveup):
        backoffs, giveups, successes = [], [], []
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              on_success=successes.append,
                              on_backoff=backoffs.append,
                              on_giveup=giveups.append,
                              max_tries=3,
                              jitter=None,
                              raise_on_giveup=raise_on_giveup,
                              interval=0)
        @_save_target
        def exceptor(*args, **kwargs):
            raise ValueError("catch me")
        if raise_on_giveup:
            with pytest.raises(ValueError):
>               exceptor(1, 2, 3, foo=1, bar=2)
tests/test_backoff.py:338:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.0s (ValueError: catch me)
______________________________________________________________________________ test_on_exception_giveup[False] ______________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          on_success=successes.append,
                          on_backoff=backoffs.append,
                          on_giveup=giveups.append,
                          max_tries=3,
                          jitter=None,
                          raise_on_giveup=raise_on_giveup,
                          interval=0)
    @_save_target
    def exceptor(*args, **kwargs):
>       raise ValueError("catch me")
E       ValueError: catch me
tests/test_backoff.py:334: ValueError
During handling of the above exception, another exception occurred:
raise_on_giveup = False
    @pytest.mark.parametrize('raise_on_giveup', [True, False])
    def test_on_exception_giveup(raise_on_giveup):
        backoffs, giveups, successes = [], [], []
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              on_success=successes.append,
                              on_backoff=backoffs.append,
                              on_giveup=giveups.append,
                              max_tries=3,
                              jitter=None,
                              raise_on_giveup=raise_on_giveup,
                              interval=0)
        @_save_target
        def exceptor(*args, **kwargs):
            raise ValueError("catch me")
        if raise_on_giveup:
            with pytest.raises(ValueError):
                exceptor(1, 2, 3, foo=1, bar=2)
        else:
>           exceptor(1, 2, 3, foo=1, bar=2)
tests/test_backoff.py:340:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.0s (ValueError: catch me)
____________________________________________________________________________ test_on_exception_giveup_predicate _____________________________________________________________________________
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          giveup=on_baz)
    def foo_bar_baz():
>       raise ValueError(vals.pop())
E       ValueError: bar
tests/test_backoff.py:370: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f298b3940>
    def test_on_exception_giveup_predicate(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        def on_baz(e):
            return str(e) == "baz"
        vals = ["baz", "bar", "foo"]
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              giveup=on_baz)
        def foo_bar_baz():
            raise ValueError(vals.pop())
        with pytest.raises(ValueError):
>           foo_bar_baz()
tests/test_backoff.py:373:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off foo_bar_baz(...) for 0.1s (ValueError: foo)
_________________________________________________________________________________ test_on_predicate_success _________________________________________________________________________________
    def test_on_predicate_success():
        backoffs, giveups, successes = [], [], []
        @backoff.on_predicate(backoff.constant,
                              on_success=successes.append,
                              on_backoff=backoffs.append,
                              on_giveup=giveups.append,
                              jitter=None,
                              interval=0)
        @_save_target
        def success(*args, **kwargs):
            # succeed after we've backed off twice
            return len(backoffs) == 2
>       success(1, 2, 3, foo=1, bar=2)
tests/test_backoff.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:58: in retry
    seconds = _next_wait(wait, ret, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off success(...) for 0.0s (False)
__________________________________________________________________________ test_on_exception_success_0_arg_jitter ___________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          Exception,
                          on_success=successes.append,
                          on_backoff=backoffs.append,
                          on_giveup=giveups.append,
                          jitter=random.random,
                          interval=0)
    @_save_target
    def succeeder(*args, **kwargs):
        # succeed after we've backed off twice
        if len(backoffs) < 2:
>           raise ValueError("catch me")
E           ValueError: catch me
tests/test_backoff.py:510: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f298730d0>
    def test_on_exception_success_0_arg_jitter(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        monkeypatch.setattr('random.random', lambda: 0)
        backoffs, giveups, successes = [], [], []
        @backoff.on_exception(backoff.constant,
                              Exception,
                              on_success=successes.append,
                              on_backoff=backoffs.append,
                              on_giveup=giveups.append,
                              jitter=random.random,
                              interval=0)
        @_save_target
        def succeeder(*args, **kwargs):
            # succeed after we've backed off twice
            if len(backoffs) < 2:
                raise ValueError("catch me")
        with pytest.deprecated_call():
>           succeeder(1, 2, 3, foo=1, bar=2)
tests/test_backoff.py:513:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off succeeder(...) for 0.0s (ValueError: catch me)
__________________________________________________________________________ test_on_predicate_success_0_arg_jitter ___________________________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29808460>
    def test_on_predicate_success_0_arg_jitter(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        monkeypatch.setattr('random.random', lambda: 0)
        backoffs, giveups, successes = [], [], []
        @backoff.on_predicate(backoff.constant,
                              on_success=successes.append,
                              on_backoff=backoffs.append,
                              on_giveup=giveups.append,
                              jitter=random.random,
                              interval=0)
        @_save_target
        def success(*args, **kwargs):
            # succeed after we've backed off twice
            return len(backoffs) == 2
        with pytest.deprecated_call():
>           success(1, 2, 3, foo=1, bar=2)
tests/test_backoff.py:561:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:58: in retry
    seconds = _next_wait(wait, ret, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off success(...) for 0.0s (False)
___________________________________________________________________________ test_on_exception_callable_max_tries ____________________________________________________________________________
    @backoff.on_exception(backoff.constant, ValueError, max_tries=lambda: 3)
    def exceptor():
        log.append(True)
>       raise ValueError()
E       ValueError
tests/test_backoff.py:598: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f298596f0>
    def test_on_exception_callable_max_tries(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        log = []
        @backoff.on_exception(backoff.constant, ValueError, max_tries=lambda: 3)
        def exceptor():
            log.append(True)
            raise ValueError()
        with pytest.raises(ValueError):
>           exceptor()
tests/test_backoff.py:601:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.9s (ValueError)
___________________________________________________________________ test_on_exception_callable_max_tries_reads_every_time ___________________________________________________________________
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          max_tries=lookup_max_tries)
    def exceptor():
>       raise ValueError()
E       ValueError
tests/test_backoff.py:619: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f298b3d90>
    def test_on_exception_callable_max_tries_reads_every_time(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        lookups = []
        def lookup_max_tries():
            lookups.append(True)
            return 3
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              max_tries=lookup_max_tries)
        def exceptor():
            raise ValueError()
        with pytest.raises(ValueError):
>           exceptor()
tests/test_backoff.py:622:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:117: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.5s (ValueError)
____________________________________________________________________________ test_on_predicate_constant_iterable ____________________________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29820a30>
    def test_on_predicate_constant_iterable(monkeypatch):
        monkeypatch.setattr('time.sleep', lambda x: None)
        waits = [1, 2, 3, 6, 9]
        backoffs = []
        giveups = []
        successes = []
        @backoff.on_predicate(
            backoff.constant,
            interval=waits,
            on_backoff=backoffs.append,
            on_giveup=giveups.append,
            on_success=successes.append,
            jitter=None,
        )
        def falsey():
            return False
>       assert not falsey()
tests/test_backoff.py:704:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_sync.py:58: in retry
    seconds = _next_wait(wait, ret, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = [1, 2, 3, 6, 9]
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'list_iterator' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off falsey(...) for 1.0s (False)
____________________________________________________________________________ test_on_exception_constant_iterable ____________________________________________________________________________
    @backoff.on_exception(
        backoff.constant,
        KeyError,
        interval=(1, 2, 3),
        on_backoff=backoffs.append,
        on_giveup=giveups.append,
        on_success=successes.append,
    )
    async def endless_exceptions():
>       raise KeyError('foo')
E       KeyError: 'foo'
tests/test_backoff_async.py:157: KeyError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29997d60>
    @pytest.mark.asyncio
    async def test_on_exception_constant_iterable(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        backoffs = []
        giveups = []
        successes = []
        @backoff.on_exception(
            backoff.constant,
            KeyError,
            interval=(1, 2, 3),
            on_backoff=backoffs.append,
            on_giveup=giveups.append,
            on_success=successes.append,
        )
        async def endless_exceptions():
            raise KeyError('foo')
        with pytest.raises(KeyError):
>           await endless_exceptions()
tests/test_backoff_async.py:160:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = (1, 2, 3)
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'tuple_iterator' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off endless_exceptions(...) for 0.1s (KeyError: 'foo')
Backing off endless_exceptions(...) for 0.1s (KeyError: 'foo')
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off endless_exceptions(...) for 0.1s (KeyError: 'foo')
_________________________________________________________________________________ test_on_exception_success _________________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          Exception,
                          on_success=log_success,
                          on_backoff=log_backoff,
                          on_giveup=log_giveup,
                          jitter=None,
                          interval=0)
    @_save_target
    async def succeeder(*args, **kwargs):
        # succeed after we've backed off twice
        if len(log['backoff']) < 2:
>           raise ValueError("catch me")
E           ValueError: catch me
tests/test_backoff_async.py:244: ValueError
During handling of the above exception, another exception occurred:
    @pytest.mark.asyncio
    async def test_on_exception_success():
        log, log_success, log_backoff, log_giveup = _log_hdlrs()
        @backoff.on_exception(backoff.constant,
                              Exception,
                              on_success=log_success,
                              on_backoff=log_backoff,
                              on_giveup=log_giveup,
                              jitter=None,
                              interval=0)
        @_save_target
        async def succeeder(*args, **kwargs):
            # succeed after we've backed off twice
            if len(log['backoff']) < 2:
                raise ValueError("catch me")
>       await succeeder(1, 2, 3, foo=1, bar=2)
tests/test_backoff_async.py:246:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off succeeder(...) for 0.0s (ValueError: catch me)
Backing off succeeder(...) for 0.0s (ValueError: catch me)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off succeeder(...) for 0.0s (ValueError: catch me)
______________________________________________________________________________ test_on_exception_giveup[True] _______________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          on_success=log_success,
                          on_backoff=log_backoff,
                          on_giveup=log_giveup,
                          raise_on_giveup=raise_on_giveup,
                          max_tries=3,
                          jitter=None,
                          interval=0)
    @_save_target
    async def exceptor(*args, **kwargs):
>       raise ValueError("catch me")
E       ValueError: catch me
tests/test_backoff_async.py:290: ValueError
During handling of the above exception, another exception occurred:
raise_on_giveup = True
    @pytest.mark.asyncio
    @pytest.mark.parametrize('raise_on_giveup', [True, False])
    async def test_on_exception_giveup(raise_on_giveup):
        log, log_success, log_backoff, log_giveup = _log_hdlrs()
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              on_success=log_success,
                              on_backoff=log_backoff,
                              on_giveup=log_giveup,
                              raise_on_giveup=raise_on_giveup,
                              max_tries=3,
                              jitter=None,
                              interval=0)
        @_save_target
        async def exceptor(*args, **kwargs):
            raise ValueError("catch me")
        if raise_on_giveup:
            with pytest.raises(ValueError):
>               await exceptor(1, 2, 3, foo=1, bar=2)
tests/test_backoff_async.py:294:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off exceptor(...) for 0.0s (ValueError: catch me)
Backing off exceptor(...) for 0.0s (ValueError: catch me)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.0s (ValueError: catch me)
______________________________________________________________________________ test_on_exception_giveup[False] ______________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          on_success=log_success,
                          on_backoff=log_backoff,
                          on_giveup=log_giveup,
                          raise_on_giveup=raise_on_giveup,
                          max_tries=3,
                          jitter=None,
                          interval=0)
    @_save_target
    async def exceptor(*args, **kwargs):
>       raise ValueError("catch me")
E       ValueError: catch me
tests/test_backoff_async.py:290: ValueError
During handling of the above exception, another exception occurred:
raise_on_giveup = False
    @pytest.mark.asyncio
    @pytest.mark.parametrize('raise_on_giveup', [True, False])
    async def test_on_exception_giveup(raise_on_giveup):
        log, log_success, log_backoff, log_giveup = _log_hdlrs()
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              on_success=log_success,
                              on_backoff=log_backoff,
                              on_giveup=log_giveup,
                              raise_on_giveup=raise_on_giveup,
                              max_tries=3,
                              jitter=None,
                              interval=0)
        @_save_target
        async def exceptor(*args, **kwargs):
            raise ValueError("catch me")
        if raise_on_giveup:
            with pytest.raises(ValueError):
                await exceptor(1, 2, 3, foo=1, bar=2)
        else:
>           await exceptor(1, 2, 3, foo=1, bar=2)
tests/test_backoff_async.py:296:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off exceptor(...) for 0.0s (ValueError: catch me)
Backing off exceptor(...) for 0.0s (ValueError: catch me)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.0s (ValueError: catch me)
____________________________________________________________________________ test_on_exception_giveup_predicate _____________________________________________________________________________
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          giveup=on_baz)
    async def foo_bar_baz():
>       raise ValueError(vals.pop())
E       ValueError: bar
tests/test_backoff_async.py:327: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29864df0>
    @pytest.mark.asyncio
    async def test_on_exception_giveup_predicate(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        def on_baz(e):
            return str(e) == "baz"
        vals = ["baz", "bar", "foo"]
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              giveup=on_baz)
        async def foo_bar_baz():
            raise ValueError(vals.pop())
        with pytest.raises(ValueError):
>           await foo_bar_baz()
tests/test_backoff_async.py:330:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off foo_bar_baz(...) for 0.6s (ValueError: foo)
Backing off foo_bar_baz(...) for 0.6s (ValueError: foo)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off foo_bar_baz(...) for 0.6s (ValueError: foo)
_______________________________________________________________________________ test_on_exception_giveup_coro _______________________________________________________________________________
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          giveup=on_baz)
    async def foo_bar_baz():
>       raise ValueError(vals.pop())
E       ValueError: bar
tests/test_backoff_async.py:348: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f2973abc0>
    @pytest.mark.asyncio
    async def test_on_exception_giveup_coro(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        async def on_baz(e):
            return str(e) == "baz"
        vals = ["baz", "bar", "foo"]
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              giveup=on_baz)
        async def foo_bar_baz():
            raise ValueError(vals.pop())
        with pytest.raises(ValueError):
>           await foo_bar_baz()
tests/test_backoff_async.py:351:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off foo_bar_baz(...) for 0.1s (ValueError: foo)
Backing off foo_bar_baz(...) for 0.1s (ValueError: foo)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off foo_bar_baz(...) for 0.1s (ValueError: foo)
_________________________________________________________________________________ test_on_predicate_success _________________________________________________________________________________
    @pytest.mark.asyncio
    async def test_on_predicate_success():
        log, log_success, log_backoff, log_giveup = _log_hdlrs()
        @backoff.on_predicate(backoff.constant,
                              on_success=log_success,
                              on_backoff=log_backoff,
                              on_giveup=log_giveup,
                              jitter=None,
                              interval=0)
        @_save_target
        async def success(*args, **kwargs):
            # succeed after we've backed off twice
            return len(log['backoff']) == 2
>       await success(1, 2, 3, foo=1, bar=2)
tests/test_backoff_async.py:371:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:86: in retry
    seconds = _next_wait(wait, ret, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off success(...) for 0.0s (False)
Backing off success(...) for 0.0s (False)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off success(...) for 0.0s (False)
____________________________________________________________________________ test_on_predicate_constant_iterable ____________________________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29854190>
    @pytest.mark.asyncio
    async def test_on_predicate_constant_iterable(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        waits = [1, 2, 3, 6, 9]
        backoffs = []
        giveups = []
        successes = []
        @backoff.on_predicate(
            backoff.constant,
            interval=waits,
            on_backoff=backoffs.append,
            on_giveup=giveups.append,
            on_success=successes.append,
            jitter=None,
        )
        async def falsey():
            return False
>       assert not await falsey()
tests/test_backoff_async.py:483:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:86: in retry
    seconds = _next_wait(wait, ret, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = [1, 2, 3, 6, 9]
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'list_iterator' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off falsey(...) for 1.0s (False)
Backing off falsey(...) for 1.0s (False)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off falsey(...) for 1.0s (False)
__________________________________________________________________________ test_on_exception_success_0_arg_jitter ___________________________________________________________________________
args = (1, 2, 3), kwargs = {'bar': 2, 'foo': 1}
    @backoff.on_exception(backoff.constant,
                          Exception,
                          on_success=log_success,
                          on_backoff=log_backoff,
                          on_giveup=log_giveup,
                          jitter=random.random,
                          interval=0)
    @_save_target
    async def succeeder(*args, **kwargs):
        # succeed after we've backed off twice
        if len(log['backoff']) < 2:
>           raise ValueError("catch me")
E           ValueError: catch me
tests/test_backoff_async.py:513: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f298145e0>
    @pytest.mark.asyncio
    async def test_on_exception_success_0_arg_jitter(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        monkeypatch.setattr('random.random', lambda: 0)
        log, log_success, log_backoff, log_giveup = _log_hdlrs()
        @backoff.on_exception(backoff.constant,
                              Exception,
                              on_success=log_success,
                              on_backoff=log_backoff,
                              on_giveup=log_giveup,
                              jitter=random.random,
                              interval=0)
        @_save_target
        async def succeeder(*args, **kwargs):
            # succeed after we've backed off twice
            if len(log['backoff']) < 2:
                raise ValueError("catch me")
        with pytest.deprecated_call():
>           await succeeder(1, 2, 3, foo=1, bar=2)
tests/test_backoff_async.py:516:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off succeeder(...) for 0.0s (ValueError: catch me)
Backing off succeeder(...) for 0.0s (ValueError: catch me)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off succeeder(...) for 0.0s (ValueError: catch me)
__________________________________________________________________________ test_on_predicate_success_0_arg_jitter ___________________________________________________________________________
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f29823520>
    @pytest.mark.asyncio
    async def test_on_predicate_success_0_arg_jitter(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        monkeypatch.setattr('random.random', lambda: 0)
        log, log_success, log_backoff, log_giveup = _log_hdlrs()
        @backoff.on_predicate(backoff.constant,
                              on_success=log_success,
                              on_backoff=log_backoff,
                              on_giveup=log_giveup,
                              jitter=random.random,
                              interval=0)
        @_save_target
        async def success(*args, **kwargs):
            # succeed after we've backed off twice
            return len(log['backoff']) == 2
        with pytest.deprecated_call():
>           await success(1, 2, 3, foo=1, bar=2)
tests/test_backoff_async.py:565:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:86: in retry
    seconds = _next_wait(wait, ret, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 0
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off success(...) for 0.0s (False)
Backing off success(...) for 0.0s (False)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off success(...) for 0.0s (False)
___________________________________________________________________________ test_on_exception_callable_max_tries ____________________________________________________________________________
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          max_tries=lookup_max_tries)
    async def exceptor():
        log.append(True)
>       raise ValueError()
E       ValueError
tests/test_backoff_async.py:607: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f299ceb00>
    @pytest.mark.asyncio
    async def test_on_exception_callable_max_tries(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        def lookup_max_tries():
            return 3
        log = []
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              max_tries=lookup_max_tries)
        async def exceptor():
            log.append(True)
            raise ValueError()
        with pytest.raises(ValueError):
>           await exceptor()
tests/test_backoff_async.py:610:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off exceptor(...) for 0.6s (ValueError)
Backing off exceptor(...) for 0.6s (ValueError)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.6s (ValueError)
___________________________________________________________________ test_on_exception_callable_max_tries_reads_every_time ___________________________________________________________________
    @backoff.on_exception(backoff.constant,
                          ValueError,
                          max_tries=lookup_max_tries)
    async def exceptor():
>       raise ValueError()
E       ValueError
tests/test_backoff_async.py:629: ValueError
During handling of the above exception, another exception occurred:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f3f299a09a0>
    @pytest.mark.asyncio
    async def test_on_exception_callable_max_tries_reads_every_time(monkeypatch):
        monkeypatch.setattr('asyncio.sleep', _await_none)
        lookups = []
        def lookup_max_tries():
            lookups.append(True)
            return 3
        @backoff.on_exception(backoff.constant,
                              ValueError,
                              max_tries=lookup_max_tries)
        async def exceptor():
            raise ValueError()
        with pytest.raises(ValueError):
>           await exceptor()
tests/test_backoff_async.py:632:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
backoff/_async.py:164: in retry
    seconds = _next_wait(wait, e, jitter, elapsed,
backoff/_common.py:33: in _next_wait
    value = wait.send(send_value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
interval = 1
    def constant(
        interval: Union[int, Iterable[float]] = 1
    ) -> Generator[float, None, None]:
        """Generator for constant intervals.
        Args:
            interval: A constant value to yield or an iterable of such values.
        """
        # Advance past initial .send() call
        yield  # type: ignore[misc]
        try:
            itr = iter(interval)  # type: ignore
        except TypeError:
            itr = itertools.repeat(interval)  # type: ignore
>       yield from itr
E       AttributeError: 'itertools.repeat' object has no attribute 'send'
backoff/_wait_gen.py:69: AttributeError
----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------
Backing off exceptor(...) for 0.0s (ValueError)
Backing off exceptor(...) for 0.0s (ValueError)
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
INFO     backoff:_common.py:103 Backing off exceptor(...) for 0.0s (ValueError)
===================================================================================== warnings summary ======================================================================================
tests/test_backoff_async.py:665
  tests/test_backoff_async.py:665: PytestDeprecationWarning: test_on_exception_coro_cancelling is asynchronous and explicitly requests the "event_loop" fixture. Asynchronous fixtures and test functions should use "asyncio.get_running_loop()" instead.
    @pytest.mark.asyncio
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================================================================== short test summary info ==================================================================================
FAILED tests/test_backoff.py::test_on_exception_constant_iterable - AttributeError: 'tuple_iterator' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_success - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_giveup[True] - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_giveup[False] - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_giveup_predicate - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_predicate_success - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_success_0_arg_jitter - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_predicate_success_0_arg_jitter - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_callable_max_tries - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_exception_callable_max_tries_reads_every_time - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff.py::test_on_predicate_constant_iterable - AttributeError: 'list_iterator' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_constant_iterable - AttributeError: 'tuple_iterator' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_success - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_giveup[True] - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_giveup[False] - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_giveup_predicate - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_giveup_coro - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_predicate_success - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_predicate_constant_iterable - AttributeError: 'list_iterator' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_success_0_arg_jitter - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_predicate_success_0_arg_jitter - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_callable_max_tries - AttributeError: 'itertools.repeat' object has no attribute 'send'
FAILED tests/test_backoff_async.py::test_on_exception_callable_max_tries_reads_every_time - AttributeError: 'itertools.repeat' object has no attribute 'send'
========================================================================= 23 failed, 96 passed, 1 warning in 1.21s ==========================================================================I'm not sure how to rewrite   | 
    
| 
           Just found jet another issue in backoff/_wait_gen.py in context of   | 
    
Signed-off-by: Tomasz Kłoczko <kloczek@github.com>
Signed-off-by: Tomasz Kłoczko <kloczek@github.com>
| 
           BTW end of this month python 3.8 will be EOSed so it would be good to merge those changes and resolve pyupgrade issue in backoff/_wait_gen.py before end of this month,  | 
    
  
      Sign up for free
      to subscribe to this conversation on GitHub.
      Already have an account?
      Sign in.
  
      
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
According to https://endoflife.date/python python 3.7 has been EOSed 27 Jun 2023.
Filter all code over
pyupgracde --py38-plus.