docs: def download_and_verify(url, md5sum, fname=None,
                          chunk_size=1024, clobber=False,
                          verbose=True):
      """
      Download a file and verify the MD5 sum.
  
      Args:
          url (str): The URL to download.
          md5sum (str): The expected MD5 sum.
          fname (Optional[str]): The filename to store the downloaded file in.
              If `None`, infer the filename from the URL. Defaults to `None`.
          chunk_size (Optional[int]): Process in chunks of this size (in Bytes).
              Defaults to 1024.
          clobber (Optional[bool]): If `True`, any existing, identical file will
              be overwritten. If `False`, the MD5 sum of any existing file with
              the destination filename will be checked. If the MD5 sum does not
              match, the existing file will be overwritten. Defaults to `False`.
          verbose (Optional[bool]): If `True` (the default), then a progress bar
              will be shownd during downloads.
  
      Returns:
          The filename the URL was downloaded to.
  
      Raises:
          DownloadError: The MD5 sum of the downloaded file does not match
              `md5sum`.
          requests.exceptions.HTTPError: There was a problem connecting to the
              URL.
      """
  
      # Determine the filename
      if fname is None:
          fname = url.split('/')[-1]
  
      # Check if the file already exists on disk
      if (not clobber) and os.path.isfile(fname):
          print('Checking existing file to see if MD5 sum matches ...')
          md5_existing = get_md5sum(fname, chunk_size=chunk_size)
          if md5_existing == md5sum:
              print('File exists. Not overwriting.')
              return fname
  
      # Make sure the directory it's going into exists
      dir_name = os.path.dirname(fname)
      if not os.path.exists(dir_name):
          os.makedirs(dir_name)
  
      sig = hashlib.md5()
  
      if verbose:
          print('Downloading {} ...'.format(url))
  
      if url.startswith('http://') or url.startswith('https://'):
          # Stream the URL as a file, copying to local disk
          with contextlib.closing(requests.get(url, stream=True)) as r:
              try:
                  r.raise_for_status()
              except requests.exceptions.HTTPError as error:
                  print('Error connecting to URL: "{}"'.format(url))
                  print(r.text)
                  raise error
  
              with open(fname, 'wb') as f:
                  content_length = r.headers.get('content-length')
                  if content_length is not None:
                      content_length = int(content_length)
                  bar = FileTransferProgressBar(content_length)
  
                  for k,chunk in enumerate(r.iter_content(chunk_size=chunk_size)):
                      f.write(chunk)
                      sig.update(chunk)
  
                      if verbose:
                          bar_val = chunk_size*(k+1)
                          if content_length is not None:
                              bar_val = min(bar_val, content_length)
                          bar.update(bar_val)
      else: # e.g., ftp://
          with contextlib.closing(urlopen(url)) as r:
              content_length = r.headers.get('content-length')
              if content_length is not None:
                  content_length = int(content_length)
              bar = FileTransferProgressBar(content_length)
  
              with open(fname, 'wb') as f:
                  k = 0
                  while True:
                      chunk = r.read(chunk_size)
  
                      if not chunk:
                          break
  
                      f.write(chunk)
                      sig.update(chunk)
  
                      if verbose:
                          k += 1
                          bar_val = chunk_size*k
                          if content_length is not None:
                              bar_val = min(bar_val, content_length)
                          bar.update(bar_val)
  
  
      if sig.hexdigest() != md5sum:
          raise DownloadError('The MD5 sum of the downloaded file is incorrect.\n'
                              + '  download: {}\n'.format(sig.hexdigest())
                              + '  expected: {}\n'.format(md5sum))
  
      return fname