docs: def fetch(self, fname, processor=None):
          """
          Get the absolute path to a file in the local storage.
  
          If it's not in the local storage, it will be downloaded. If the hash of the file
          in local storage doesn't match the one in the registry, will download a new copy
          of the file. This is considered a sign that the file was updated in the remote
          storage. If the hash of the downloaded file still doesn't match the one in the
          registry, will raise an exception to warn of possible file corruption.
  
          Post-processing actions sometimes need to be taken on downloaded files
          (unzipping, conversion to a more efficient format, etc). If these actions are
          time or memory consuming, it would be best to do this only once when the file is
          actually downloaded. Use the *processor* argument to specify a function that is
          executed after the downloaded (if required) to perform these actions. See below.
  
          Parameters
          ----------
          fname : str
              The file name (relative to the *base_url* of the remote data storage) to
              fetch from the local storage.
          processor : None or callable
              If not None, then a function (or callable object) that will be called
              before returning the full path and after the file has been downloaded (if
              required). See below.
  
          Returns
          -------
          full_path : str
              The absolute path (including the file name) of the file in the local
              storage.
  
          Notes
          -----
  
          Processor functions should have the following format:
  
          .. code:: python
  
              def myprocessor(fname, action, update):
                  '''
                  Processes the downloaded file and returns a new file name.
  
                  The function **must** take as arguments (in order):
  
                  fname : str
                      The full path of the file in the local data storage
                  action : str
                      Either:
                      "download" (file doesn't exist and will be downloaded),
                      "update" (file is outdated and will be downloaded), or
                      "fetch" (file exists and is updated so no download is necessary).
                  pooch : pooch.Pooch
                      The instance of the Pooch class that is calling this function.
  
                  The return value can be anything but is usually a full path to a file
                  (or list of files). This is what will be returned by *fetch* in place of
                  the original file path.
                  '''
                  ...
  
          """
          self._assert_file_in_registry(fname)
  
          # Create the local data directory if it doesn't already exist
          if not self.abspath.exists():
              os.makedirs(str(self.abspath))
  
          full_path = self.abspath / fname
  
          in_storage = full_path.exists()
          if not in_storage:
              action = "download"
          elif in_storage and file_hash(str(full_path)) != self.registry[fname]:
              action = "update"
          else:
              action = "fetch"
  
          if action in ("download", "update"):
              action_word = dict(download="Downloading", update="Updating")
              warn(
                  "{} data file '{}' from remote data store '{}' to '{}'.".format(
                      action_word[action], fname, self.get_url(fname), str(self.path)
                  )
              )
              self._download_file(fname)
  
          if processor is not None:
              return processor(str(full_path), action, self)
  
          return str(full_path)