docs: def cache_file(filename):
      """Caches a file locally if possible.
  
      If caching was succesfull, or if
      the file was previously successfully cached, this method returns the
      path to the local copy of the file. If not, it returns the path to
      the original file.
  
      Parameters
      ----------
      filename : str
          Remote file to cache locally
  
      Returns
      -------
      output : str
          Updated (if needed) filename to use to access the remote
          file.
  
      """
      dataset_local_dir = config.local_data_path
      dataset_remote_dir = os.path.dirname(filename)
      if dataset_remote_dir == "" or dataset_local_dir == "":
          log.debug("Local dataset cache is deactivated")
  
      remote_name = filename
  
      # Check if a local directory for data has been defined. Otherwise,
      # do not locally copy the data
      if dataset_local_dir == "":
          return filename
  
      common_msg = ("Message from fuel local cache of dataset"
                    "(specified by the environment variable "
                    "FUEL_LOCAL_DATA_PATH): ")
      # Make sure the file to cache exists and really is a file
      if not os.path.exists(remote_name):
          log.error(
              "Error : Specified file {} does not exist".format(remote_name))
          return filename
  
      if not os.path.isfile(remote_name):
          log.error(
              "Error : Specified name {} is not a file".format(remote_name))
          return filename
  
      if not remote_name.startswith(dataset_remote_dir):
          log.warning(
              common_msg +
              "We cache in the local directory only what is"
              " under $FUEL_DATA_PATH: {}".format(remote_name))
          return filename
  
      # Create the $FUEL_LOCAL_DATA_PATH folder if needed
      safe_mkdir(dataset_local_dir,
                 (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
                  stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP |
                  stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH))
  
      # Determine local path to which the file is to be cached
      local_name = os.path.join(dataset_local_dir,
                                os.path.relpath(remote_name,
                                                dataset_remote_dir))
  
      # Create the folder structure to receive the remote file
      local_folder = os.path.split(local_name)[0]
      try:
          safe_mkdir(local_folder)
      except Exception:
          log.warning(
              (common_msg +
               "While creating the directory {}, we got an error."
               " We won't cache to the local disk.").format(local_folder))
          return filename
  
      # Acquire writelock on the local file to prevent the possibility
      # of any other process modifying it while we cache it if needed.
      # Also, if another process is currently caching the same file,
      # it forces the current process to wait for it to be done before
      # using the file.
      if not os.access(local_folder, os.W_OK):
          log.warning(common_msg +
                      "Local folder {} isn't writable."
                      " This is needed for synchronization."
                      " We will use the remote version."
                      " Manually fix the permission."
                      .format(local_folder))
          return filename
      get_writelock(local_name)
  
      # If the file does not exist locally, consider creating it
      if not os.path.exists(local_name):
  
          # Check that there is enough space to cache the file
          if not check_enough_space(dataset_local_dir, remote_name,
                                    local_name):
              log.warning(common_msg +
                          "File {} not cached: Not enough free space"
                          .format(remote_name))
              release_writelock()
              return filename
  
          # There is enough space; make a local copy of the file
          copy_from_server_to_local(dataset_remote_dir, dataset_local_dir,
                                    remote_name, local_name)
          log.info(common_msg + "File {} has been locally cached to {}"
                   .format(remote_name, local_name))
      elif os.path.getmtime(remote_name) > os.path.getmtime(local_name):
          remote_modified_time = time.strftime(
              '%Y-%m-%d %H:%M:%S',
              time.localtime(os.path.getmtime(remote_name)))
          local_modified_time = time.strftime(
              '%Y-%m-%d %H:%M:%S',
              time.localtime(os.path.getmtime(local_name)))
          log.warning(common_msg +
                      "File {} in cache will not be used: The remote file "
                      "(modified {}) is newer than the locally cached file "
                      "{} (modified {})."
                      .format(remote_name, remote_modified_time,
                              local_name, local_modified_time))
          release_writelock()
          return filename
      elif os.path.getsize(local_name) != os.path.getsize(remote_name):
          log.warning(common_msg +
                      "File {} not cached: The remote file ({} bytes) is of "
                      "a different size than the locally cached file {} "
                      "({} bytes). The local cache might be corrupt."
                      .format(remote_name, os.path.getsize(remote_name),
                              local_name, os.path.getsize(local_name)))
          release_writelock()
          return filename
      elif not os.access(local_name, os.R_OK):
          log.warning(common_msg +
                      "File {} in cache isn't readable. We will use the"
                      " remote version. Manually fix the permission."
                      .format(local_name))
          release_writelock()
          return filename
      else:
          log.debug("File {} has previously been locally cached to {}"
                    .format(remote_name, local_name))
  
      # Obtain a readlock on the downloaded file before releasing the
      # writelock. This is to prevent having a moment where there is no
      # lock on this file which could give the impression that it is
      # unused and therefore safe to delete.
      get_readlock(pid, local_name)
      release_writelock()
  
      return local_name