code: def retry(attempts=3, delay=1.0, max_delay=None, backoff=1):
      """
      Retry decorator
  
      Parameters
      ----------
      attempts : int, default 3
          The number of attempts.
      delay : float, default 1
          Initial delay in seconds.
      max_delay : float, optional
          The max delay between attempts.
      backoff : float, default 1
          The multiplier to delay after each attempt.
      """
  
      def decorate(func):
          @functools.wraps(func)
          def wrapper(*args, **kwargs):
              remaining_attempts = attempts
              curr_delay = delay
              while remaining_attempts > 0:
                  try:
                      return func(*args, **kwargs)
                  except Exception as err:
                      remaining_attempts -= 1
                      last_exception = err
                      curr_delay *= backoff
                      if max_delay:
                          curr_delay = min(curr_delay, max_delay)
                      time.sleep(curr_delay)
              raise last_exception
  
          return wrapper
  
      return decorate
  
imports: import functools
  import os
  import pathlib
  import subprocess
  import sys
  import time
  import urllib.request
  import pytest
  from pytest_lazyfixture import lazy_fixture
  import hypothesis
  from ..conftest import groups, defaults
  from pyarrow import set_timezone_db_path
  from pyarrow.util import find_free_port
label_desc: Use image node_id 9 for calling a global function with example usage: retry(attempts, delay, max_delay, backoff) and returns: decorate, wrapper, func