docstr: Saves the data present in the `path` the `metaflow_card_cache` directory or to the `save_path`.
docstr_tok: ["Saves","the","data","present","in","the","`","path","`","the","`","metaflow_card_cache","`","directory","or","to","the","`","save_path","`","."]
code: def cache_locally(self, path, save_path=None):
      """
      Saves the data present in the `path` the `metaflow_card_cache` directory or to the `save_path`.
      """
      # todo : replace this function with the FileCache
      if save_path is None:
          if not is_file_present(self._temp_card_save_path):
              LocalStorage._makedirs(self._temp_card_save_path)
      else:
          save_dir = os.path.dirname(save_path)
          if save_dir != "" and not is_file_present(save_dir):
              LocalStorage._makedirs(os.path.dirname(save_path))
  
      with self._backend.load_bytes([path]) as get_results:
          for key, path, meta in get_results:
              if path is not None:
                  main_path = path
                  if save_path is None:
                      file_name = key.split("/")[-1]
                      main_path = os.path.join(
                          self._temp_card_save_path, file_name
                      )
                  else:
                      main_path = save_path
                  shutil.copy(path, main_path)
                  return main_path
  
imports: from collections import namedtuple
  from io import BytesIO
  import os
  import json
  import shutil
  from metaflow.plugins.datastores.local_storage import LocalStorage
  from metaflow.metaflow_config import CARD_S3ROOT, CARD_LOCALROOT, DATASTORE_LOCAL_DIR, CARD_SUFFIX, CARD_AZUREROOT, CARD_GSROOT, SKIP_CARD_DUALWRITE
  import metaflow.metaflow_config
  from .exception import CardNotPresentException
label_desc: Use image node_id 18 for calling the CardDatastore obj's underlying member method code with example usage: obj.cache_locally(path, save_path) and returns: main_path