class_docstr: Base class for the downloaders
class_docstr_tok: ["Base","class","for","the","downloaders"]
docstr: Fetch content from a url into a file.
  
  Very similar to _download but lacks any "file" management and decodes
  content
  
  Parameters
  ----------
  url: str
    URL to download
  cache: bool, optional
    If None, config is consulted to determine whether results should be
    cached. Cache is operating based on url, so no verification of any
    kind is carried out
  
  Returns
  -------
  bytes, dict
    content, headers
docstr_tok: ["Fetch","content","from","a","url","into","a","file",".","Very","similar","to","_download","but","lacks","any","``","file","''","management","and","decodes","content","Parameters","--","--","--","--","--","url",":","str","URL","to","download","cache",":","bool",",","optional","If","None",",","config","is","consulted","to","determine","whether","results","should","be","cached",".","Cache","is","operating","based","on","url",",","so","no","verification","of","any","kind","is","carried","out","Returns","--","--","--","-","bytes",",","dict","content",",","headers"]
code: def _fetch(
      self,
      url,
      cache=None,
      size=None,
      allow_redirects=True,
      decode=True,
  ):
      """Fetch content from a url into a file.
  
      Very similar to _download but lacks any "file" management and decodes
      content
  
      Parameters
      ----------
      url: str
        URL to download
      cache: bool, optional
        If None, config is consulted to determine whether results should be
        cached. Cache is operating based on url, so no verification of any
        kind is carried out
  
      Returns
      -------
      bytes, dict
        content, headers
      """
      lgr.log(
          3,
          "_fetch(%r, cache=%r, size=%r, allow_redirects=%r)",
          url,
          cache,
          size,
          allow_redirects,
      )
      if cache is None:
          cache = cfg.obtain("datalad.crawl.cache", default=False)
  
      if cache:
          cache_key = msgpack.dumps(url)
          lgr.debug("Loading content for url %s from cache", url)
          res = self.cache.get(cache_key)
          if res is not None:
              try:
                  return msgpack.loads(res, encoding="utf-8")
              except Exception as exc:
                  ce = CapturedException(exc)
                  lgr.warning(
                      "Failed to unpack loaded from cache for %s: %s",
                      url,
                      ce,
                  )
  
      downloader_session = self.get_downloader_session(
          url, allow_redirects=allow_redirects
      )
  
      target_size = downloader_session.size
      if size is not None:
          if size == 0:
              # no download of the content was requested -- just return headers and be done
              return None, downloader_session.headers
          target_size = min(size, target_size)
  
      # FETCH CONTENT
      try:
          # Consider to improve to make it animated as well, or shorten here
          # pbar = ui.get_progressbar(label=url, fill_text=filepath, total=target_size)
          content = downloader_session.download(size=size)
          # pbar.finish()
          downloaded_size = len(content)
  
          # now that we know size based on encoded content, let's decode into string type
          if isinstance(content, bytes) and decode:
              content = ensure_unicode(content)
          # downloaded_size = os.stat(temp_filepath).st_size
  
          self._verify_download(
              url, downloaded_size, target_size, None, content=content
          )
  
      except (AccessDeniedError, IncompleteDownloadError) as e:
          raise
      except Exception as e:
          ce = CapturedException(e)
          lgr.error("Failed to fetch %s: %s", url, ce)
          raise DownloadError(ce) from e  # for now
  
      if cache:
          # apparently requests' CaseInsensitiveDict is not serialazable
          # TODO:  may be we should reuse that type everywhere, to avoid
          # out own handling for case-handling
          self.cache[cache_key] = msgpack.dumps(
              (content, dict(downloader_session.headers))
          )
  
      return content, downloader_session.headers
  
imports: import msgpack
  import os
  import sys
  import time
  from abc import ABCMeta, abstractmethod
  import os.path
  from os.path import exists, join, isdir
  from ..None import cfg
  from ..ui import ui
  from ..utils import auto_repr, ensure_unicode, unlink
  from .credentials import CompositeCredential
  from datalad.downloaders import CREDENTIAL_TYPES
  from ..support.exceptions import AccessDeniedError, AccessPermissionExpiredError, AnonymousAccessDeniedError, CapturedException, DownloadError, IncompleteDownloadError, UnaccountedDownloadError
  from ..support.locking import InterProcessLock, try_lock, try_lock_informatively
  from logging import getLogger
label_desc: Use image node_id 12 for calling the BaseDownloader obj's underlying member method code with example usage: obj._fetch(url, cache, size, allow_redirects, decode) and returns: content,  downloader_session, None,  downloader_session, msgpack