content: from __future__ import annotations
  
  import time
  
  
  __all__ = ["Deadline"]
  
  
  class Deadline:
      """
      Manage timeouts across multiple steps.
  
      Args:
          timeout: Time available in seconds or :obj:`None` if there is no limit.
  
      """
  
      def __init__(self, timeout: float | None) -> None:
          self.deadline: float | None
          if timeout is None:
              self.deadline = None
          else:
              self.deadline = time.monotonic() + timeout
  
      def timeout(self, *, raise_if_elapsed: bool = True) -> float | None:
          """
          Calculate a timeout from a deadline.
  
          Args:
              raise_if_elapsed: Whether to raise :exc:`TimeoutError`
                  if the deadline lapsed.
  
          Raises:
              TimeoutError: If the deadline lapsed.
  
          Returns:
              Time left in seconds or :obj:`None` if there is no limit.
  
          """
          if self.deadline is None:
              return None
          timeout = self.deadline - time.monotonic()
          if raise_if_elapsed and timeout <= 0:
              raise TimeoutError("timed out")
          return timeout
  