<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fetch(self, url, listener, chunk_size_bytes=None, timeout_secs=None):
 """Fetches data from the given URL notifying listener of all lifecycle events. :param string url: the url to GET data from :param listener: the listener to notify of all download lifecycle events :param chunk_size_bytes: the chunk size to use for buffering data, 10 KB by default :param timeout_secs: the maximum time to wait for data to be available, 1 second by default :raises: Fetcher.Error if there was a problem fetching all data from the given url """

    if not isinstance(listener, self.Listener):
      raise ValueError('listener must be a Listener instance, given {}'.format(listener))

    chunk_size_bytes = chunk_size_bytes or 10 * 1024
    timeout_secs = timeout_secs or 1.0

    with closing(self._fetch(url, timeout_secs=timeout_secs)) as resp:
      if resp.status_code != requests.codes.ok:
        listener.status(resp.status_code)
        raise self.PermanentError('Fetch of {} failed with status code {}'
                                  .format(url, resp.status_code),
                                  response_code=resp.status_code)
      listener.status(resp.status_code, content_length=resp.size)

      read_bytes = 0
      for data in resp.iter_content(chunk_size_bytes=chunk_size_bytes):
        listener.recv_chunk(data)
        read_bytes += len(data)
      if resp.size and read_bytes != resp.size:
        raise self.Error('Expected {} bytes, read {}'.format(resp.size, read_bytes))
      listener.finished()